Skip to content

Commit

Permalink
Merge pull request #95 from steveorourke/main
Browse files Browse the repository at this point in the history
Add optional use and alg fields to JWK
  • Loading branch information
iwarapter authored Aug 12, 2023
2 parents 5267091 + 5eff152 commit 9f5e94a
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 45 deletions.
10 changes: 7 additions & 3 deletions docs/data-sources/from_certificate.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ Calculates a JSON Web Key Set from a given certificate.

```terraform
data "jwks_from_certificate" "pem_example" {
key = file("${path.module}/certificate.pem")
pem = file("${path.module}/certificate.pem")
}
data "jwks_from_certificate" "pem_example_2" {
key = file("${path.module}/certificate.pem")
pem = file("${path.module}/certificate.pem")
kid = "123"
use = "sig"
alg = "RS256"
}
```

Expand All @@ -33,7 +35,9 @@ data "jwks_from_certificate" "pem_example_2" {

### Optional

- `kid` (String) Used to override the kid field of the JWK
- `kid` (String) Used to override the `kid` field of the JWK
- `use` (String) Used to populate the `use` field of the JWK.
- `alg` (String) Used to populate the `alg` field of the JWK.

### Read-Only

Expand Down
6 changes: 5 additions & 1 deletion docs/data-sources/from_key.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ data "jwks_from_key" "base64_der_example" {
data "jwks_from_key" "base64_der_example" {
key = data.aws_kms_public_key.example.public_key
kid = "123"
use = "sig"
alg = "RS256"
}
```

Expand All @@ -46,7 +48,9 @@ data "jwks_from_key" "base64_der_example" {

### Optional

- `kid` (String) Used to populate the kid field of the JWK.
- `kid` (String) Used to populate the `kid` field of the JWK.
- `use` (String) Used to populate the `use` field of the JWK.
- `alg` (String) Used to populate the `alg` field of the JWK.

### Read-Only

Expand Down
7 changes: 4 additions & 3 deletions examples/data-sources/jwks_from_certificate/data-source.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

data "jwks_from_certificate" "pem_example" {
key = file("${path.module}/certificate.pem")
pem = file("${path.module}/certificate.pem")
}

data "jwks_from_certificate" "pem_example_2" {
key = file("${path.module}/certificate.pem")
pem = file("${path.module}/certificate.pem")
kid = "123"
use = "sig"
alg = "RS256"
}
2 changes: 2 additions & 0 deletions examples/data-sources/jwks_from_key/data-source.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ data "jwks_from_key" "base64_der_example" {
data "jwks_from_key" "base64_der_example" {
key = data.aws_kms_public_key.example.public_key
kid = "123"
use = "sig"
alg = "RS256"
}
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ require (
github.com/hashicorp/terraform-plugin-go v0.8.0
github.com/hashicorp/terraform-plugin-mux v0.6.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.13.0
github.com/lestrrat-go/jwx v1.2.22
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921
github.com/lestrrat-go/jwx v1.2.26
golang.org/x/crypto v0.9.0
)

require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/goccy/go-json v0.9.6 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/uuid v1.1.2 // indirect
Expand Down Expand Up @@ -50,7 +50,7 @@ require (
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.0 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/cli v1.1.2 // indirect
Expand All @@ -67,9 +67,9 @@ require (
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.2 // indirect
github.com/zclconf/go-cty v1.10.0 // indirect
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 // indirect
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect
Expand Down
70 changes: 43 additions & 27 deletions go.sum

Large diffs are not rendered by default.

36 changes: 34 additions & 2 deletions internal/sdkv2provider/data_source_jwks_from_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ func dataSourceJwksFromCertificateSchema() map[string]*schema.Schema {
Optional: true,
Description: `Used to override the kid field of the JWK`,
},
"use": {
Type: schema.TypeString,
Optional: true,
Description: `Used to populate the use field of the JWK`,
},
"alg": {
Type: schema.TypeString,
Optional: true,
Description: `Used to populate the alg field of the JWK`,
},
"jwks": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -68,7 +78,17 @@ func dataSourceJwksFromCertificateRead(_ context.Context, d *schema.ResourceData
kid = calculateCertificateThumbprint(leaf)
}

key, err := calculateKey(leaf, certificates, kid)
var use string
if u, ok := d.GetOk("use"); ok {
use = u.(string)
}

var alg string
if u, ok := d.GetOk("alg"); ok {
alg = u.(string)
}

key, err := calculateKey(leaf, certificates, kid, use, alg)
if err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -123,7 +143,7 @@ func calculateCertificateThumbprint(x509Cert *x509.Certificate) string {
return base64.StdEncoding.EncodeToString(hash.Sum(nil))
}

func calculateKey(x509Cert *x509.Certificate, chain []*x509.Certificate, kid string) (jwk.Key, error) {
func calculateKey(x509Cert *x509.Certificate, chain []*x509.Certificate, kid, use, alg string) (jwk.Key, error) {
key, err := jwk.New(x509Cert.PublicKey.(*rsa.PublicKey))
if err != nil {
return nil, err
Expand All @@ -141,6 +161,18 @@ func calculateKey(x509Cert *x509.Certificate, chain []*x509.Certificate, kid str
return nil, err
}

if use != "" {
if err = key.Set(jwk.KeyUsageKey, use); err != nil {
return nil, err
}
}

if alg != "" {
if err = key.Set(jwk.AlgorithmKey, alg); err != nil {
return nil, err
}
}

return key, nil
}

Expand Down
34 changes: 34 additions & 0 deletions internal/sdkv2provider/data_source_jwks_from_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,18 @@ func TestAccJwksFromCertificateDataSource(t *testing.T) {
Config: testAccJwksFromCertificateDataSourceConfig(WrongOrderCertificatePem),
ExpectError: regexp.MustCompile("unable to validate the certificate signature chain"),
},
{
Config: testAccJwksFromCertificateDataSourceWithUseConfig(SingleCertificatePem, "sig"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "jwks", `{"e":"AQAB","kid":"IZbkJobc7ZEyBG8Gc98ImVqsyIrycTgBgi0NCRNIxxc=","kty":"RSA","n":"rfx-dsNbFZNH1mbQr-Mp5drB8HTjW3b6bMn_xWKSF1jdA0Guon9bKXJAeSvGlblI6p6P1OhgoxiNbnHTqyzgfAhl6UzTaFqPo30ZEZdKreBS-Fdrm4qXMfV_S_0vAVLQ_8_BYVefA9pN-Z8svRF8IPsAHUPCIpMhNZHFPwHbhsItCD9WAAz2lOat9wf3MMzrWeniuxp3Gd4yB0O0lXM0sgki7VHM5tG7IJ8Dht_ubb1tkvmMdEX7oObtuvOi6BnfjKa98v6IQYOUHmEbDYqKcvlkwy8JFFS5m3Du_7Y_SpMJGvxr9cIV2wJjekTm2AvgBcOySCWc0n25IloQuGQefQ","use":"sig","x5c":["MIIDujCCAqKgAwIBAgIUdsLKEuCH3vMu/nUo55XTi8r9tP0wDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMCVUsxEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEQMA4GA1UEChMHcmFpZGlhbTEQMA4GA1UECxMHUmFpZGlhbTEfMB0GA1UEAxMWUmFpZGlhbSBSb290IERFTU8gLSBHMTAeFw0yMTA5MjAxNTU5MDBaFw0yNjA5MTkxNTU5MDBaMHUxCzAJBgNVBAYTAlVLMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xEDAOBgNVBAoTB3JhaWRpYW0xEDAOBgNVBAsTB1JhaWRpYW0xHzAdBgNVBAMTFlJhaWRpYW0gUm9vdCBERU1PIC0gRzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt/H52w1sVk0fWZtCv4ynl2sHwdONbdvpsyf/FYpIXWN0DQa6if1spckB5K8aVuUjqno/U6GCjGI1ucdOrLOB8CGXpTNNoWo+jfRkRl0qt4FL4V2ubipcx9X9L/S8BUtD/z8FhV58D2k35nyy9EXwg+wAdQ8IikyE1kcU/AduGwi0IP1YADPaU5q33B/cwzOtZ6eK7GncZ3jIHQ7SVczSyCSLtUczm0bsgnwOG3+5tvW2S+Yx0Rfug5u2686LoGd+Mpr3y/ohBg5QeYRsNiopy+WTDLwkUVLmbcO7/tj9Kkwka/Gv1whXbAmN6RObYC+AFw7JIJZzSfbkiWhC4ZB59AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTKbfFcygg4So8lz+x8g3OfldEqFDANBgkqhkiG9w0BAQsFAAOCAQEAUPfBDQbdIDxN990G85i5kmUw6MdPKU2kxLTZukRUX/Lc3cEGprOpAO8sisgSnIJ9KfCNlouEu74DlwhsYr9E1aaAS7b5b2bauIttJ0Xtj+wRz1TDmIqQKpMppQLcuvXLLRPy/1K38Ol4LVkaoWiOep1eS+OPx9DX+JwTI1CZavAWX9INmRFqyl7qOY6eAqaxtiAeRc3YkE6B42DEFiB0n0lG/CAgjtwmB1qymTo3IDZS0rjj+R7n4NbnUzIoE9L/dwkPqW8F2pRvvoX3lJ9LnFlazEzzNt1/VqOwpTs40gW60r4etSsy5ZMQWHuOhGtqftRdHTxjxIjvvk1XFYoTDg=="],"x5t#S256":"IZbkJobc7ZEyBG8Gc98ImVqsyIrycTgBgi0NCRNIxxc="}`),
),
},
{
Config: testAccJwksFromCertificateDataSourceWithAlgConfig(SingleCertificatePem, "RS256"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "jwks", `{"alg":"RS256","e":"AQAB","kid":"IZbkJobc7ZEyBG8Gc98ImVqsyIrycTgBgi0NCRNIxxc=","kty":"RSA","n":"rfx-dsNbFZNH1mbQr-Mp5drB8HTjW3b6bMn_xWKSF1jdA0Guon9bKXJAeSvGlblI6p6P1OhgoxiNbnHTqyzgfAhl6UzTaFqPo30ZEZdKreBS-Fdrm4qXMfV_S_0vAVLQ_8_BYVefA9pN-Z8svRF8IPsAHUPCIpMhNZHFPwHbhsItCD9WAAz2lOat9wf3MMzrWeniuxp3Gd4yB0O0lXM0sgki7VHM5tG7IJ8Dht_ubb1tkvmMdEX7oObtuvOi6BnfjKa98v6IQYOUHmEbDYqKcvlkwy8JFFS5m3Du_7Y_SpMJGvxr9cIV2wJjekTm2AvgBcOySCWc0n25IloQuGQefQ","x5c":["MIIDujCCAqKgAwIBAgIUdsLKEuCH3vMu/nUo55XTi8r9tP0wDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMCVUsxEDAOBgNVBAgTB0VuZ2xhbmQxDzANBgNVBAcTBkxvbmRvbjEQMA4GA1UEChMHcmFpZGlhbTEQMA4GA1UECxMHUmFpZGlhbTEfMB0GA1UEAxMWUmFpZGlhbSBSb290IERFTU8gLSBHMTAeFw0yMTA5MjAxNTU5MDBaFw0yNjA5MTkxNTU5MDBaMHUxCzAJBgNVBAYTAlVLMRAwDgYDVQQIEwdFbmdsYW5kMQ8wDQYDVQQHEwZMb25kb24xEDAOBgNVBAoTB3JhaWRpYW0xEDAOBgNVBAsTB1JhaWRpYW0xHzAdBgNVBAMTFlJhaWRpYW0gUm9vdCBERU1PIC0gRzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt/H52w1sVk0fWZtCv4ynl2sHwdONbdvpsyf/FYpIXWN0DQa6if1spckB5K8aVuUjqno/U6GCjGI1ucdOrLOB8CGXpTNNoWo+jfRkRl0qt4FL4V2ubipcx9X9L/S8BUtD/z8FhV58D2k35nyy9EXwg+wAdQ8IikyE1kcU/AduGwi0IP1YADPaU5q33B/cwzOtZ6eK7GncZ3jIHQ7SVczSyCSLtUczm0bsgnwOG3+5tvW2S+Yx0Rfug5u2686LoGd+Mpr3y/ohBg5QeYRsNiopy+WTDLwkUVLmbcO7/tj9Kkwka/Gv1whXbAmN6RObYC+AFw7JIJZzSfbkiWhC4ZB59AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTKbfFcygg4So8lz+x8g3OfldEqFDANBgkqhkiG9w0BAQsFAAOCAQEAUPfBDQbdIDxN990G85i5kmUw6MdPKU2kxLTZukRUX/Lc3cEGprOpAO8sisgSnIJ9KfCNlouEu74DlwhsYr9E1aaAS7b5b2bauIttJ0Xtj+wRz1TDmIqQKpMppQLcuvXLLRPy/1K38Ol4LVkaoWiOep1eS+OPx9DX+JwTI1CZavAWX9INmRFqyl7qOY6eAqaxtiAeRc3YkE6B42DEFiB0n0lG/CAgjtwmB1qymTo3IDZS0rjj+R7n4NbnUzIoE9L/dwkPqW8F2pRvvoX3lJ9LnFlazEzzNt1/VqOwpTs40gW60r4etSsy5ZMQWHuOhGtqftRdHTxjxIjvvk1XFYoTDg=="],"x5t#S256":"IZbkJobc7ZEyBG8Gc98ImVqsyIrycTgBgi0NCRNIxxc="}`),
),
},
},
})
}
Expand Down Expand Up @@ -228,3 +240,25 @@ EOF
}
`, data, kid)
}

func testAccJwksFromCertificateDataSourceWithUseConfig(data string, use string) string {
return fmt.Sprintf(`
data "jwks_from_certificate" "test" {
pem = <<EOF
%s
EOF
use = "%s"
}
`, data, use)
}

func testAccJwksFromCertificateDataSourceWithAlgConfig(data string, alg string) string {
return fmt.Sprintf(`
data "jwks_from_certificate" "test" {
pem = <<EOF
%s
EOF
alg = "%s"
}
`, data, alg)
}
24 changes: 24 additions & 0 deletions internal/sdkv2provider/data_source_jwks_from_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ func dataSourceJwksFromKeySchema() map[string]*schema.Schema {
Optional: true,
Description: `Used to populate the kid field of the JWK.`,
},
"use": {
Type: schema.TypeString,
Optional: true,
Description: `Used to populate the use field of the JWK.`,
},
"alg": {
Type: schema.TypeString,
Optional: true,
Description: `Used to populate the alg field of the JWK.`,
},
"jwks": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -90,6 +100,20 @@ func dataSourceJwksFromKeyRead(_ context.Context, d *schema.ResourceData, m inte
return diag.FromErr(err)
}
}
use, ok := d.GetOk("use")
if ok {
err = key.Set(jwk.KeyUsageKey, use.(string))
if err != nil {
return diag.FromErr(err)
}
}
alg, ok := d.GetOk("alg")
if ok {
err = key.Set(jwk.AlgorithmKey, alg.(string))
if err != nil {
return diag.FromErr(err)
}
}
b, err := json.Marshal(key)
if err != nil {
return diag.FromErr(err)
Expand Down
34 changes: 34 additions & 0 deletions internal/sdkv2provider/data_source_jwks_from_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,18 @@ func TestAccJwksFromKeyDataSource(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "jwks", `{"crv":"P-384","kid":"123","kty":"EC","x":"QnSqFbKGdEiz_g0CoZFXBAvsMMbMBqqnZ3jJ_zrLxuBShDTmrsRoU7MCOALbt04f","y":"FoRI8H06aS1Wq1XsAbMiMLUqpl5joOWeUChxyPb0v-7B86IE9299UHBpbAfcnthd"}`),
),
},
{
Config: testAccJwksFromKeyWithUseDataSourceConfig(PublicKey, "sig"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "jwks", `{"e":"AQAB","kty":"RSA","n":"gUElV5mwqkloIrM8ZNZ72gSCcnSJt7-_Usa5G-D15YQUAdf9c1zEekTfHgDP-04nw_uFNFaE5v1RbHaPxhZYVg5ZErNCa_hzn-x10xzcepeS3KPVXcxae4MR0BEegvqZqJzN9loXsNL_c3H_B-2Gle3hTxjlWFb3F5qLgR-4Mf4ruhER1v6eHQa_nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr-sTSxfh7r6v24u_vp_QTmBIAlNPgadVAZw17iNNb7vjV7Gwl_5gHXonCUKURaV--dBNLrHIZpqcAM8wHRph8mD1EfL9hsz77pHewxolBATV-7Q","use":"sig"}`),
),
},
{
Config: testAccJwksFromKeyWithAlgDataSourceConfig(PublicKey, "RS256"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "jwks", `{"alg":"RS256","e":"AQAB","kty":"RSA","n":"gUElV5mwqkloIrM8ZNZ72gSCcnSJt7-_Usa5G-D15YQUAdf9c1zEekTfHgDP-04nw_uFNFaE5v1RbHaPxhZYVg5ZErNCa_hzn-x10xzcepeS3KPVXcxae4MR0BEegvqZqJzN9loXsNL_c3H_B-2Gle3hTxjlWFb3F5qLgR-4Mf4ruhER1v6eHQa_nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr-sTSxfh7r6v24u_vp_QTmBIAlNPgadVAZw17iNNb7vjV7Gwl_5gHXonCUKURaV--dBNLrHIZpqcAM8wHRph8mD1EfL9hsz77pHewxolBATV-7Q"}`),
),
},
},
})
}
Expand Down Expand Up @@ -166,6 +178,28 @@ EOF
`, data, kid)
}

func testAccJwksFromKeyWithUseDataSourceConfig(data, use string) string {
return fmt.Sprintf(`
data "jwks_from_key" "test" {
key = <<EOF
%s
EOF
use = "%s"
}
`, data, use)
}

func testAccJwksFromKeyWithAlgDataSourceConfig(data, alg string) string {
return fmt.Sprintf(`
data "jwks_from_key" "test" {
key = <<EOF
%s
EOF
alg = "%s"
}
`, data, alg)
}

func privateKeyDer() string {
block, _ := pem.Decode([]byte(PrivateKey))
return base64.StdEncoding.EncodeToString(block.Bytes)
Expand Down

0 comments on commit 9f5e94a

Please sign in to comment.