-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dependabot/go_modules/github.com/dvsekhvalno…
…v/jose2go-1.6.0
- Loading branch information
Showing
10 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Auto-generated by fogg. Do not edit | ||
# Make improvements in fogg, so that everyone can benefit. | ||
|
||
export TERRAFORM_VERSION := 1.3.6 | ||
export TF_PLUGIN_CACHE_DIR := ../../..//.terraform.d/plugin-cache | ||
|
||
include ../../..//scripts/module.mk | ||
|
||
|
||
help: ## display help for this makefile | ||
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' | ||
.PHONY: help |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
This is a module that creates an Okta app that's bounded to a KMS Key. You can use the KMS key to sign JWTs that are compatible with the Okta /token endpoints. After you create the Okta App, you can work with the Okta Token endpoint by roughly following these steps: | ||
1. Creating a header with this kind of structure: `{{"alg": "<algorithm>", "typ": "JWT"}}`. To identify algorithms. Here are the algorithm options as of Febuary 5, 2025: | ||
``` | ||
signing_algs = ( | ||
('RSASSA_PSS_SHA_256', 'PS256', 'sha256'), | ||
('RSASSA_PSS_SHA_384', 'PS384', 'sha384'), | ||
('RSASSA_PSS_SHA_512', 'PS512', 'sha512'), | ||
('RSASSA_PKCS1_V1_5_SHA_256', 'RS256', 'sha256'), | ||
('RSASSA_PKCS1_V1_5_SHA_384', 'RS384', 'sha384'), | ||
('RSASSA_PKCS1_V1_5_SHA_512', 'RS512', 'sha512'), | ||
('ECDSA_SHA_256', 'ES256', 'sha256'), | ||
('ECDSA_SHA_384', 'ES384', 'sha384'), | ||
('ECDSA_SHA_512', 'ES512', 'sha512'), | ||
) | ||
``` | ||
source: https://github.com/jmtapio/python-jwt-kms/blob/552668588c5eec5eff9346740660239baef22428/jwt_kms/jwa.py | ||
So if your KMS key has type `RSASSA_PKCS1_V1_5_SHA_256`, your `alg` is `RS256`. If you want to dive deeper, you can look at the RFC section here: https://datatracker.ietf.org/doc/html/rfc7518#section-3.1 | ||
|
||
2. Creating a payload with this kind of structure with this format: | ||
```json | ||
{ | ||
"exp": <future timestamp>, | ||
"iat": <number of seconds since Jan 1, 1970 UTC>, | ||
"iss": client_id, | ||
"aud": [okta_token_endpoint], | ||
"sub": client_id, | ||
} | ||
``` | ||
each attribute can be found here: https://developer.okta.com/docs/api/openapi/okta-oauth/guides/client-auth/#token-claims-for-client-authentication-with-client-secret-or-private-key-jwt | ||
|
||
3. Base64-encode values from step #1 and #2 and strip out the equal signs (`=`). | ||
4. Concatenate the values from step #3 with a header.payload format, then use the AWS KMS `sign` operation from whatever AWS SDK you use. If you used algorithm type `RS256`, then your KMS Sign operation should use SigningAlgorithm type `RSASSA_PKCS1_V1_5_SHA_256`. You should be able to parse out the "Signature" value from your kms `sign` output. | ||
5. Construct the JWT in this way: base64header.base64payload.signature-from-step-4 | ||
|
||
After you construct the JWT, you're ready to use it with the Okta Token endpoint here: https://developer.okta.com/docs/api/openapi/okta-oauth/guides/client-auth/#jwt-with-private-key | ||
you just need to set the JWT from step 5 to the "client_assertion" value while making the request. | ||
|
||
<!-- START --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3 | | ||
| <a name="requirement_okta"></a> [okta](#requirement\_okta) | ~> 4.0 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | n/a | | ||
| <a name="provider_external"></a> [external](#provider\_external) | n/a | | ||
| <a name="provider_okta"></a> [okta](#provider\_okta) | ~> 4.0 | | ||
|
||
## Modules | ||
|
||
| Name | Source | Version | | ||
|------|--------|---------| | ||
| <a name="module_params"></a> [params](#module\_params) | github.com/chanzuckerberg/cztack//aws-ssm-params-writer | v0.63.3 | | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [okta_app_oauth.idp_api](https://registry.terraform.io/providers/okta/okta/latest/docs/resources/app_oauth) | resource | | ||
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | ||
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | | ||
| [external_external.jwks_info](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source | | ||
|
||
## Inputs | ||
|
||
| Name | Description | Type | Default | Required | | ||
|------|-------------|------|---------|:--------:| | ||
| <a name="input_friendly_key_identifier"></a> [friendly\_key\_identifier](#input\_friendly\_key\_identifier) | A name for the key configuration in the okta app, something you will recognize for yourself and the project. | `string` | n/a | yes | | ||
| <a name="input_kms_key_id"></a> [kms\_key\_id](#input\_kms\_key\_id) | The Key ID or alias of the AWS KMS Key. It has to be available in the same region and account as the configured provider. | `string` | n/a | yes | | ||
| <a name="input_okta_configuration"></a> [okta\_configuration](#input\_okta\_configuration) | Details needed to configure an okta app. Its token auth method is private\_key\_jwt | <pre>object({<br> label = string<br> type = string<br> grant_types = list(string)<br> omit_secret = bool<br> response_types = list(string)<br> pkce_required = bool<br> })</pre> | n/a | yes | | ||
| <a name="input_tags"></a> [tags](#input\_tags) | These values are used to derive the path in the param store where to write the Okta App Configuration metadata. | <pre>object({<br> project = string,<br> env = string,<br> service = string,<br> owner = string,<br> })</pre> | n/a | yes | | ||
| <a name="input_write_metadata_to_params"></a> [write\_metadata\_to\_params](#input\_write\_metadata\_to\_params) | Whether you want to include the clientID and KMS Key Alias grouped together as securestring parameters in JSON format. If true, module will write these details to a path based on the env, project and service"<br> They will be written following path:<br> /<project>-<env>-<service>/client\_id<br> /<project>-<env>-<service>/kms\_key\_id<br><br> (the module may add secrets over time)<br><br> Note that these values should correspond with the consuming service's tagset so secrets are placed in the path they expect. | `bool` | n/a | yes | | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_client_id"></a> [client\_id](#output\_client\_id) | n/a | | ||
| <a name="output_kms_id"></a> [kms\_id](#output\_kms\_id) | n/a | | ||
<!-- END --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Auto-generated by fogg. Do not edit | ||
# Make improvements in fogg, so that everyone can benefit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import boto3, json | ||
from cryptography.hazmat.primitives.serialization import load_der_public_key | ||
from jose import jwk, constants | ||
import sys | ||
|
||
aws_account_id = sys.argv[1] | ||
kms_key_id = sys.argv[2] | ||
region = sys.argv[3] | ||
|
||
sts_client = boto3.client("sts", region_name=region) | ||
assume_role_client = sts_client.assume_role(RoleArn=f"arn:aws:iam::{aws_account_id}:role/tfe-si", RoleSessionName='FetchKMSInformation') | ||
credentials = assume_role_client["Credentials"] | ||
kms_session = boto3.Session( | ||
aws_access_key_id=credentials["AccessKeyId"], | ||
aws_secret_access_key= credentials["SecretAccessKey"], | ||
aws_session_token= credentials["SessionToken"], | ||
region_name=region, | ||
) | ||
kms_client = kms_session.client("kms", region_name=region) | ||
|
||
# try to get the public key in bytes | ||
output = kms_client.get_public_key( | ||
KeyId=kms_key_id, | ||
) | ||
assert output.get("PublicKey") is not None | ||
public_key = load_der_public_key(output["PublicKey"]) | ||
jwks_vals = jwk.RSAKey(algorithm=constants.Algorithms.RS256, key=public_key).to_dict() | ||
print(json.dumps(jwks_vals)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
data "aws_caller_identity" "current" {} | ||
data "aws_region" "current" {} | ||
# uses a key in core-platform-infra to generate credentials for this workspace | ||
data "external" "jwks_info" { | ||
program = ["bash", "${path.module}/run.sh", path.module, data.aws_caller_identity.current.account_id, var.kms_key_id, data.aws_region.current.name] | ||
} | ||
|
||
resource "okta_app_oauth" "idp_api" { | ||
label = var.okta_configuration.label | ||
type = var.okta_configuration.type | ||
grant_types = var.okta_configuration.grant_types | ||
response_types = var.okta_configuration.response_types | ||
token_endpoint_auth_method = "private_key_jwt" | ||
pkce_required = var.okta_configuration.pkce_required | ||
jwks { | ||
e = data.external.jwks_info.result.e | ||
kty = data.external.jwks_info.result.kty | ||
kid = var.friendly_key_identifier | ||
n = data.external.jwks_info.result.n | ||
} | ||
} | ||
|
||
|
||
module "params" { | ||
source = "github.com/chanzuckerberg/cztack//aws-ssm-params-writer?ref=v0.63.3" | ||
project = var.tags.project | ||
env = var.tags.env | ||
service = var.tags.service | ||
owner = var.tags.owner | ||
|
||
parameters = { | ||
"client_id" = okta_app_oauth.idp_api.client_id | ||
"kms_key_id" = var.kms_key_id | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
output "client_id" { | ||
value = okta_app_oauth.idp_api.id | ||
} | ||
|
||
output "kms_id" { | ||
value = var.kms_key_id | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
|
||
# need to install python-jose instead of jose: https://stackoverflow.com/a/65103147 | ||
pip install boto3 cryptography python-jose 2>&1 > /dev/null | ||
python3 $1/get_jwks_for_okta.py $2 $3 $4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dependencies { | ||
paths = [ | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
variable "kms_key_id" { | ||
type = string | ||
description = "The Key ID or alias of the AWS KMS Key. It has to be available in the same region and account as the configured provider." | ||
} | ||
|
||
variable "okta_configuration" { | ||
type = object({ | ||
label = string | ||
type = string | ||
grant_types = list(string) | ||
omit_secret = bool | ||
response_types = list(string) | ||
pkce_required = bool | ||
}) | ||
description = "Details needed to configure an okta app. Its token auth method is private_key_jwt" | ||
} | ||
|
||
variable "friendly_key_identifier" { | ||
type = string | ||
description = "A name for the key configuration in the okta app, something you will recognize for yourself and the project." | ||
} | ||
|
||
variable "write_metadata_to_params" { | ||
type = bool | ||
description = <<EOF | ||
Whether you want to include the clientID and KMS Key Alias grouped together as securestring parameters in JSON format. If true, module will write these details to a path based on the env, project and service" | ||
They will be written following path: | ||
/<project>-<env>-<service>/client_id | ||
/<project>-<env>-<service>/kms_key_id | ||
(the module may add secrets over time) | ||
Note that these values should correspond with the consuming service's tagset so secrets are placed in the path they expect. | ||
EOF | ||
} | ||
|
||
variable "tags" { | ||
type = object({ | ||
project = string, | ||
env = string, | ||
service = string, | ||
owner = string, | ||
}) | ||
|
||
description = <<EOF | ||
These values are used to derive the path in the param store where to write the Okta App Configuration metadata. | ||
EOF | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
terraform { | ||
required_providers { | ||
okta = { | ||
source = "okta/okta" | ||
version = "~> 4.0" | ||
} | ||
} | ||
|
||
required_version = ">= 1.3" | ||
} |