Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/cam access key #2182

Merged
merged 7 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/2182.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
tencentcloud_cam_access_key
```
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.17

require (
cloud.google.com/go/iam v1.0.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c
github.com/agext/levenshtein v1.2.3 // indirect
github.com/aws/aws-sdk-go v1.36.30
github.com/beevik/etree v1.2.0
Expand All @@ -14,6 +15,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.3.0
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/hcl/v2 v2.13.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0
Expand All @@ -29,7 +31,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.736
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apm v1.0.624
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.760
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.591
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb v1.0.699
Expand Down Expand Up @@ -140,6 +142,7 @@ require (
github.com/charithe/durationcheck v0.0.10 // indirect
github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/curioswitch/go-reassign v0.2.0 // indirect
github.com/daixiang0/gci v0.10.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down Expand Up @@ -182,7 +185,6 @@ require (
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-getter v1.4.0 // indirect
github.com/hashicorp/go-hclog v1.2.1 // indirect
Expand Down Expand Up @@ -308,7 +310,7 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 // indirect
golang.org/x/mod v0.9.0 // indirect
Expand Down
11 changes: 11 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZ
github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
Expand Down Expand Up @@ -146,6 +148,7 @@ github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox7
github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k=
github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY=
github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
Expand All @@ -163,6 +166,8 @@ github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
Expand Down Expand Up @@ -784,6 +789,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756 h1:dx4aBdOW
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756/go.mod h1:lwWeh6aHg6GlttTMp+VIVtpZOtmpP6DQnnYWpyYW37Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409 h1:ToZpNh78SVdKakkeR9YV1a65tjtC4NJl+hrJqTuhO3g=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409/go.mod h1:U24yUxCDruJLayOsP/onO2E/7+9ljeNsNO+phu+PeiM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760 h1:Ky9dRsTL2HXKWUrTFpQFZWQ1TrM+o+P35kczR7thalo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760/go.mod h1:AAfdrxknvUedvigxbbzKQLxN+1EG5NPbytpiqmfuFvU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.520 h1:n4FN0PI+1MVWi+RGQbD/cElXjquZQK0K1h1Z1nNWNWw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.520/go.mod h1:gzI+2Qd/iUfPPQQjW30k0G3mJ3m7tXeXrydJMm8jsOo=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.760 h1:oGY4IigfIw0iQKh3/cOY29KBeEeFbvJft69e0beyfdI=
Expand Down Expand Up @@ -1087,8 +1094,11 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down Expand Up @@ -1297,6 +1307,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
193 changes: 193 additions & 0 deletions tencentcloud/pkgkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package tencentcloud

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"strings"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/hashicorp/go-cleanhttp"
)

const (
kbPrefix = "keybase:"
)

func DecodeJSONFromReader(r io.Reader, out interface{}) error {
if r == nil {
return fmt.Errorf("'io.Reader' being decoded is nil")
}
if out == nil {
return fmt.Errorf("output parameter 'out' is nil")
}

dec := json.NewDecoder(r)

// While decoding JSON values, interpret the integer values as `json.Number`s instead of `float64`.
dec.UseNumber()

// Since 'out' is an interface representing a pointer, pass it to the decoder without an '&'
return dec.Decode(out)
}

func FetchKeybasePubkeys(input []string) (map[string]string, error) {
client := cleanhttp.DefaultClient()
if client == nil {
return nil, fmt.Errorf("unable to create an http client")
}

if len(input) == 0 {
return nil, nil
}

usernames := make([]string, 0, len(input))
for _, v := range input {
if strings.HasPrefix(v, kbPrefix) {
usernames = append(usernames, strings.TrimSuffix(strings.TrimPrefix(v, kbPrefix), "\n"))
}
}

if len(usernames) == 0 {
return nil, nil
}

ret := make(map[string]string, len(usernames))
url := fmt.Sprintf("https://keybase.io/_/api/1.0/user/lookup.json?usernames=%s&fields=public_keys", strings.Join(usernames, ","))
resp, err := client.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()

type PublicKeys struct {
Primary struct {
Bundle string
}
}

type LThem struct {
PublicKeys `json:"public_keys"`
}

type KbResp struct {
Status struct {
Name string
}
Them []LThem
}

out := &KbResp{
Them: []LThem{},
}

if err := DecodeJSONFromReader(resp.Body, out); err != nil {
return nil, err
}

if out.Status.Name != "OK" {
return nil, fmt.Errorf("got non-OK response: %q", out.Status.Name)
}

missingNames := make([]string, 0, len(usernames))
var keyReader *bytes.Reader
serializedEntity := bytes.NewBuffer(nil)
for i, themVal := range out.Them {
if themVal.Primary.Bundle == "" {
missingNames = append(missingNames, usernames[i])
continue
}
keyReader = bytes.NewReader([]byte(themVal.Primary.Bundle))
entityList, err := openpgp.ReadArmoredKeyRing(keyReader)
if err != nil {
return nil, err
}
if len(entityList) != 1 {
return nil, fmt.Errorf("primary key could not be parsed for user %q", usernames[i])
}
if entityList[0] == nil {
return nil, fmt.Errorf("primary key was nil for user %q", usernames[i])
}

serializedEntity.Reset()
err = entityList[0].Serialize(serializedEntity)
if err != nil {
return nil, fmt.Errorf("serializing entity for user %q: %w", usernames[i], err)
}

// The API returns values in the same ordering requested, so this should properly match
ret[kbPrefix+usernames[i]] = base64.StdEncoding.EncodeToString(serializedEntity.Bytes())
}

if len(missingNames) > 0 {
return nil, fmt.Errorf("unable to fetch keys for user(s) %q from keybase", strings.Join(missingNames, ","))
}

return ret, nil
}

func EncryptShares(input [][]byte, pgpKeys []string) ([]string, [][]byte, error) {
if len(input) != len(pgpKeys) {
return nil, nil, fmt.Errorf("mismatch between number items to encrypt and number of PGP keys")
}
encryptedShares := make([][]byte, 0, len(pgpKeys))
entities, err := GetEntities(pgpKeys)
if err != nil {
return nil, nil, err
}
for i, entity := range entities {
ctBuf := bytes.NewBuffer(nil)
pt, err := openpgp.Encrypt(ctBuf, []*openpgp.Entity{entity}, nil, nil, nil)
if err != nil {
return nil, nil, fmt.Errorf("setting up encryption for PGP message: %w", err)
}
_, err = pt.Write(input[i])
if err != nil {
return nil, nil, fmt.Errorf("encrypting PGP message: %w", err)
}
pt.Close()
encryptedShares = append(encryptedShares, ctBuf.Bytes())
}

fingerprints, err := GetFingerprints(nil, entities)
if err != nil {
return nil, nil, err
}

return fingerprints, encryptedShares, nil
}

func GetFingerprints(pgpKeys []string, entities []*openpgp.Entity) ([]string, error) {
if entities == nil {
var err error
entities, err = GetEntities(pgpKeys)

if err != nil {
return nil, err
}
}
ret := make([]string, 0, len(entities))
for _, entity := range entities {
ret = append(ret, fmt.Sprintf("%x", entity.PrimaryKey.Fingerprint))
}
return ret, nil
}

func GetEntities(pgpKeys []string) ([]*openpgp.Entity, error) {
ret := make([]*openpgp.Entity, 0, len(pgpKeys))
for _, keystring := range pgpKeys {
data, err := base64.StdEncoding.DecodeString(keystring)
if err != nil {
return nil, fmt.Errorf("decoding given PGP key: %w", err)
}
entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
if err != nil {
return nil, fmt.Errorf("parsing given PGP key: %w", err)
}
ret = append(ret, entity)
}
return ret, nil
}
2 changes: 2 additions & 0 deletions tencentcloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ Cloud Access Management(CAM)
tencentcloud_cam_role_sso
tencentcloud_cam_service_linked_role
tencentcloud_cam_mfa_flag
tencentcloud_cam_access_key
tencentcloud_cam_user_saml_config
tencentcloud_cam_user_permission_boundary_attachment

Expand Down Expand Up @@ -2660,6 +2661,7 @@ func Provider() *schema.Provider {
"tencentcloud_cam_saml_provider": resourceTencentCloudCamSAMLProvider(),
"tencentcloud_cam_service_linked_role": resourceTencentCloudCamServiceLinkedRole(),
"tencentcloud_cam_mfa_flag": resourceTencentCloudCamMfaFlag(),
"tencentcloud_cam_access_key": resourceTencentCloudCamAccessKey(),
"tencentcloud_cam_user_saml_config": resourceTencentCloudCamUserSamlConfig(),
"tencentcloud_cam_user_permission_boundary_attachment": resourceTencentCloudCamUserPermissionBoundaryAttachment(),
"tencentcloud_ciam_user_group": resourceTencentCloudCiamUserGroup(),
Expand Down
Loading
Loading