external-secrets/kubernetes-external-secrets

Always tries to use instance profile instead of service account

hongkongkiwi opened this issue · 2 comments

Hi everyone,

I've restricted access to the instance profile as detailed by amazon here. For reference I'm using the region "us-gov-west-1", that's the only difference, but everything else looks (from my eyes) correct.

But in my logs, I can see that it always tries to look for the instance role and does not try my service role.

{"message":"Missing credentials in config","errno":"ETIMEDOUT","code":"CredentialsError","syscall":"connect","address":"169.254.169.254","port":80,"time":"2020-10-22T16:31:31.521Z","originalError":{"message":"Could not load credentials from ChainableTemporaryCredentials","errno":"ETIMEDOUT","code":"CredentialsError","syscall":"connect","address":"169.254.169.254","port":80,"time":"2020-10-22T16:31:31.521Z","originalError":{"message":"Missing credentials in config","errno":"ETIMEDOUT","code":"CredentialsError","syscall":"connect","address":"169.254.169.254","port":80,"time":"2020-10-22T16:31:31.521Z","originalError":{"message":"Could not load credentials from any providers","errno":"ETIMEDOUT","code":"CredentialsError","syscall":"connect","address":"169.254.169.254","port":80,"time":"2020-10-22T16:31:31.521Z","originalError":{"message":"EC2 Metadata roleName request returned error","errno":"ETIMEDOUT","code":"ETIMEDOUT","syscall":"connect","address":"169.254.169.254","port":80,"time":"2020-10-22T16:31:31.521Z","originalError":{"errno":"ETIMEDOUT","code":"ETIMEDOUT","syscall":"connect","address":"169.254.169.254","port":80,"message":"connect ETIMEDOUT 169.254.169.254:80"}}}}},"stack":"Error: connect ETIMEDOUT 169.254.169.254:80\n    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)","type":"Error","msg":"failure while polling the secret myapp/myapp-db-pass"}
{"msg":"updating status for myapp/myapp-db-pass to: ERROR, Missing credentials in config"}

Here are the values I'm setting up with:

env:
  AWS_REGION: us-gov-west-1
  AWS_DEFAULT_REGION: us-gov-west-1
  DISABLE_POLLING: false
  LOG_LEVEL: debug
  ROLE_PERMITTED_ANNOTATION: iam.amazonaws.com/permitted

customResourceManagerDisabled: false

crds:
  create: false

rbac:
  create: true

serviceAccount:
  name: external-secrets
  create: true
  annotations:
    eks.amazonaws.com/role-arn: arn:aws-us-gov:iam::<my_account_id>:role/EKSExternalSecretsManager

securityContext:
  fsGroup: 65534
  runAsNonRoot: false

image:
  repository: godaddy/kubernetes-external-secrets
  tag: 6.0.0

Here's my ExternalSecret:

apiVersion: 'kubernetes-client.io/v1'
kind: ExternalSecret
metadata:
  name: my-db-pass
  namespace: mynamespace
spec:
  backendType: secretsManager
  region: us-gov-west-1
  roleArn: "arn:aws-us-gov:iam::<my_account_id>:role/EKSApp"
  data:
    - key: /dev/db
      name: password

Here's the EKSExternalSecretsManager role trust policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws-us-gov:iam::<my_acc_id>:oidc-provider/oidc.eks.us-gov-west-1.amazonaws.com/id/<MY_ID>"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.us-gov-west-1.amazonaws.com/id/<MY_ID>:sub": "system:serviceaccount:external-secrets:*"
        }
      }
    }
  ]
}

This role has the permissions to assume the EKSApp role, which in turn trusts this role. So that seems setup properly.

Looking inside the external-secrets pod these values are set:

AWS_ROLE_ARN=arn:aws-us-gov:iam::<my_acc_id>:role/EKSExternalSecretsManager
AWS_DEFAULT_REGION=us-gov-west-1
AWS_REGION=us-gov-west-1
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token

Here is the decoded token above

{
 "aud": [
  "sts.amazonaws.com"
 ],
 "exp": 1603419185,
 "iat": 1603415434,
 "iss": "https://oidc.eks.us-gov-west-1.amazonaws.com/id/<my_id>",
 "kubernetes.io": {
  "namespace": "external-secrets",
  "pod": {
   "name": "external-secrets-kubernetes-external-secrets-dbc9f877b-zhb6b",
   "uid": "bb5efd79-c066-401f-8b19-7c39390e46f7"
  },
  "serviceaccount": {
   "name": "external-secrets",
   "uid": "f5b8cebe-38b6-4529-8086-c494751a9592"
  }
 },
 "nbf": 1603415434,
 "sub": "system:serviceaccount:external-secrets:external-secrets",
 "jti": "cda27c2d-07fd-468e-80bb-fe4ff797fdfc"
}

When I use the node.js commands from #290 to manually authenticate inside the pod this is the error that seems to show

Error [CredentialsError]: Missing credentials in config
    at Request.extractError (/app/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/app/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/app/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/app/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/app/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /app/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/app/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/app/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'CredentialsError',
  time: 2020-10-23T01:17:13.398Z,
  requestId: '9cce30e2-36bc-4d16-8e09-a39ebe5a8af2',
  statusCode: 400,
  retryable: true,
  originalError: {
    message: 'Could not load credentials from TokenFileWebIdentityCredentials',
    code: 'CredentialsError',
    time: 2020-10-23T01:17:13.398Z,
    requestId: '9cce30e2-36bc-4d16-8e09-a39ebe5a8af2',
    statusCode: 400,
    retryable: true,
    originalError: {
      message: 'Incorrect token audience',
      code: 'InvalidIdentityToken',
      time: 2020-10-23T01:17:13.397Z,
      requestId: '9cce30e2-36bc-4d16-8e09-a39ebe5a8af2',
      statusCode: 400,
      retryable: true
    }
  }
} null

This error seems misleading as I saw in #290 he saw the same thing, but turns out it was something else.

I'm really lost! What else can I do to debug?

I saw a few other posts about this issue saying there was some bugs in the external-secrets code, but since I'm using the latest 6.0.0 release, I would have to assume these are solved. Should I be using a fork?

I have resolved this. For future referenece of others some Amazon accounts need to use a different STS url. By default the mutating webhook inserts sts.amazonaws.com , in my case for my account I had to use the us-gov sts endpoint. This can be changed with the following annotation in the service account. Here's an example:

serviceAccount:
  name: external-secrets
  create: true
  annotations:
    eks.amazonaws.com/role-arn: arn:aws-us-gov:iam::<MY_ACCOUNT_ID>:role/<MY_ROLE_NAME>
    eks.amazonaws.com/audience: sts.us-gov-west-1.amazonaws.com

Thanks for reporting back! Everything in the initial post really did look correct to me so nice to know the reason :)