Start produces the authentication values required for AWS_MSK_IAM. It produces the following json as a byte array, making use of the aws-sdk to produce the signed output. { "version" : "2020_10_22", "host" : "<broker host>", "user-agent": "<user agent string from the client>", "action":
(ctx context.Context)
| 63 | // "x-amz-signature" : "<AWS SigV4 signature computed by the client>" |
| 64 | // } |
| 65 | func (m *Mechanism) Start(ctx context.Context) (sess sasl.StateMachine, ir []byte, err error) { |
| 66 | saslMeta := sasl.MetadataFromContext(ctx) |
| 67 | if saslMeta == nil { |
| 68 | return nil, nil, errors.New("missing sasl metadata") |
| 69 | } |
| 70 | |
| 71 | query := url.Values{ |
| 72 | queryActionKey: {signAction}, |
| 73 | } |
| 74 | |
| 75 | signUrl := url.URL{ |
| 76 | Scheme: "kafka", |
| 77 | Host: saslMeta.Host, |
| 78 | Path: "/", |
| 79 | RawQuery: query.Encode(), |
| 80 | } |
| 81 | |
| 82 | req, err := http.NewRequest("GET", signUrl.String(), nil) |
| 83 | if err != nil { |
| 84 | return nil, nil, err |
| 85 | } |
| 86 | |
| 87 | signTime := m.SignTime |
| 88 | if signTime.IsZero() { |
| 89 | signTime = time.Now() |
| 90 | } |
| 91 | |
| 92 | expiry := m.Expiry |
| 93 | if expiry == 0 { |
| 94 | expiry = 5 * time.Minute |
| 95 | } |
| 96 | |
| 97 | header, err := m.Signer.Presign(req, nil, signService, m.Region, expiry, signTime) |
| 98 | if err != nil { |
| 99 | return nil, nil, err |
| 100 | } |
| 101 | signedMap := map[string]string{ |
| 102 | signVersionKey: signVersion, |
| 103 | signHostKey: signUrl.Host, |
| 104 | signUserAgentKey: signUserAgent, |
| 105 | signActionKey: signAction, |
| 106 | } |
| 107 | // The protocol requires lowercase keys. |
| 108 | for key, vals := range header { |
| 109 | signedMap[strings.ToLower(key)] = vals[0] |
| 110 | } |
| 111 | for key, vals := range req.URL.Query() { |
| 112 | signedMap[strings.ToLower(key)] = vals[0] |
| 113 | } |
| 114 | |
| 115 | signedJson, err := json.Marshal(signedMap) |
| 116 | return m, signedJson, err |
| 117 | } |
| 118 | |
| 119 | func (m *Mechanism) Next(ctx context.Context, challenge []byte) (bool, []byte, error) { |
| 120 | // After the initial step, the authentication is complete |