goauthentik / goauthentik/authentik

Service Account authentication using AWS presigned sts urls

Open
#22,912 0 comments 0 reactions 0 assignees View on GitHub
enhancement enhancement/confirmed
Dominant language
Python
Stars
25.6k
Forks
2k
Avg merge
1d 1h
Merged PRs (30d)
644

Description

### Is your feature request related to a problem?

I have ECS and Lambda services running in aws, they run with a least privilege IAM role. AWS provides infrastructure to allow these services to obtain short lived access keys for accessing aws services - i don't have to manage any secrets.

However these services need to call each other, IAM doesn't really have a good answer for this so we turn to an idp to issue a JWT. Authentik supports this, but a service account results in a secret to manage. I don't want to have to manage secrets.

It would be ideal if authentik could authenticate using IAM instead of a user/pass (ie secret token) to authenticate.

### Describe the solution you'd like

Instead of [basic auth](https://docs.goauthentik.io/sys-mgmt/service-accounts/#authentication-with-service-accounts) to obtain a service account jwt from authentik, make a new custom scheme that uses signed sts urls.

It is possible to obtain a signed url for the command `aws sts get-caller-identity` which is the aws equivalent of `whoami`. This URL much like the s3 signed urls many people may be more familiar with exposes no secret information, but does allow an unauthenticated user to call the url and access the resource for a limited time.

Demonstration:

```python
import boto3
import botocore.auth
import botocore.awsrequest
import subprocess

creds = boto3.Session().get_credentials().get_frozen_credentials()
request = botocore.awsrequest.AWSRequest(
method="GET",
url="https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15",
)
botocore.auth.SigV4QueryAuth(creds, "sts", "us-east-1", expires=10).add_auth(request)

print(request.url)
```

The url this produces looks like this:

`https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAZOJT...%2Fus-east-1%2Fsts%2Faws4_request&X-Amz-Date=20260608T000741Z&X-Amz-Expires=10&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2...&X-Amz-Signature=e33fa...592a206def75f90a`

and when accessed returns a xml payload like this:

```xml


arn:aws:sts::123456789012:assumed-role/rolename/sessionname
AROAxxxx:xxxx
123456789012


36935302-4410-4d9a-8834-2ee5755b88a0

```

now you have a sts session arn, which can be trivially turned back into a role ARN with some string manipulation. the role name can be mapped to the principal that is being authenticated, and you have proof that the caller is who they say they are, without any secrets.

Security considerations:
* validate the url as bing a aws sts server (regexes must be anchored)
* replay attack (expires should be short, but otherwise better for replay that user:pass)
* confused deputy, services may sign a request not understanding that it could be used for authentication
* it's possible to add additional arguments in the url that sts includes in the signature but ignores otherwise which could be useful to mitigate confused deputy `purpose=authentik` perhaps

This solves needing secrets for machine accounts running in aws. I'm not familiar enough with other cloud environments to say if there is parallels that would work for azure/gcp.

This does need some additional config mapping on the service account
* disallow password auth when IAM auth is enabled
* store and manage mapping of IAM role ARNs that are allowed to authenticate to service account

Maybe something like:
```
Authorization: AwsAttested
```

### Describe alternatives that you've considered

secrets are ok, but its nice not to have them

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.