Skip to content

Commit a81c9ed

Browse files
WeiMengXSWeiMengXS
andauthored
Feat/cam access key (#2182)
* feat: cam acc * feat: cam acc * feat: add resource * feat: changelog * feat: encrypted * feat: encrypted * feat: encrypted --------- Co-authored-by: WeiMengXS <nickcchen@tencent.com>
1 parent 455fe9f commit a81c9ed

File tree

187 files changed

+31116
-1238
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

187 files changed

+31116
-1238
lines changed

.changelog/2182.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
tencentcloud_cam_access_key
3+
```

go.mod

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.17
44

55
require (
66
cloud.google.com/go/iam v1.0.0 // indirect
7+
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c
78
github.com/agext/levenshtein v1.2.3 // indirect
89
github.com/aws/aws-sdk-go v1.36.30
910
github.com/beevik/etree v1.2.0
@@ -14,6 +15,7 @@ require (
1415
github.com/google/go-querystring v1.1.0 // indirect
1516
github.com/google/uuid v1.3.0
1617
github.com/hashicorp/errwrap v1.1.0 // indirect
18+
github.com/hashicorp/go-cleanhttp v0.5.2
1719
github.com/hashicorp/go-multierror v1.1.1
1820
github.com/hashicorp/hcl/v2 v2.13.0
1921
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0
@@ -29,7 +31,7 @@ require (
2931
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.736
3032
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apm v1.0.624
3133
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756
32-
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409
34+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760
3335
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.760
3436
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.591
3537
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdb v1.0.699
@@ -140,6 +142,7 @@ require (
140142
github.com/charithe/durationcheck v0.0.10 // indirect
141143
github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect
142144
github.com/clbanning/mxj v1.8.4 // indirect
145+
github.com/cloudflare/circl v1.3.3 // indirect
143146
github.com/curioswitch/go-reassign v0.2.0 // indirect
144147
github.com/daixiang0/gci v0.10.1 // indirect
145148
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -182,7 +185,6 @@ require (
182185
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
183186
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
184187
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
185-
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
186188
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
187189
github.com/hashicorp/go-getter v1.4.0 // indirect
188190
github.com/hashicorp/go-hclog v1.2.1 // indirect
@@ -308,7 +310,7 @@ require (
308310
go.uber.org/atomic v1.7.0 // indirect
309311
go.uber.org/multierr v1.6.0 // indirect
310312
go.uber.org/zap v1.24.0 // indirect
311-
golang.org/x/crypto v0.5.0 // indirect
313+
golang.org/x/crypto v0.7.0 // indirect
312314
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
313315
golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 // indirect
314316
golang.org/x/mod v0.9.0 // indirect

go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZ
7474
github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc=
7575
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
7676
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
77+
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
78+
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
7779
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
7880
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
7981
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
@@ -146,6 +148,7 @@ github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox7
146148
github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k=
147149
github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY=
148150
github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc=
151+
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
149152
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
150153
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
151154
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -163,6 +166,8 @@ github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
163166
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
164167
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
165168
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
169+
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
170+
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
166171
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
167172
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
168173
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -784,6 +789,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756 h1:dx4aBdOW
784789
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.756/go.mod h1:lwWeh6aHg6GlttTMp+VIVtpZOtmpP6DQnnYWpyYW37Y=
785790
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409 h1:ToZpNh78SVdKakkeR9YV1a65tjtC4NJl+hrJqTuhO3g=
786791
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.409/go.mod h1:U24yUxCDruJLayOsP/onO2E/7+9ljeNsNO+phu+PeiM=
792+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760 h1:Ky9dRsTL2HXKWUrTFpQFZWQ1TrM+o+P35kczR7thalo=
793+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760/go.mod h1:AAfdrxknvUedvigxbbzKQLxN+1EG5NPbytpiqmfuFvU=
787794
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.520 h1:n4FN0PI+1MVWi+RGQbD/cElXjquZQK0K1h1Z1nNWNWw=
788795
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.520/go.mod h1:gzI+2Qd/iUfPPQQjW30k0G3mJ3m7tXeXrydJMm8jsOo=
789796
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.760 h1:oGY4IigfIw0iQKh3/cOY29KBeEeFbvJft69e0beyfdI=
@@ -1101,8 +1108,11 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
11011108
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
11021109
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
11031110
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
1111+
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
11041112
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
11051113
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
1114+
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
1115+
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
11061116
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
11071117
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
11081118
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1311,6 +1321,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
13111321
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
13121322
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
13131323
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
1324+
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
13141325
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13151326
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13161327
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

tencentcloud/pkgkey.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package tencentcloud
2+
3+
import (
4+
"bytes"
5+
"encoding/base64"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
"strings"
10+
11+
"github.com/ProtonMail/go-crypto/openpgp"
12+
"github.com/ProtonMail/go-crypto/openpgp/packet"
13+
"github.com/hashicorp/go-cleanhttp"
14+
)
15+
16+
const (
17+
kbPrefix = "keybase:"
18+
)
19+
20+
func DecodeJSONFromReader(r io.Reader, out interface{}) error {
21+
if r == nil {
22+
return fmt.Errorf("'io.Reader' being decoded is nil")
23+
}
24+
if out == nil {
25+
return fmt.Errorf("output parameter 'out' is nil")
26+
}
27+
28+
dec := json.NewDecoder(r)
29+
30+
// While decoding JSON values, interpret the integer values as `json.Number`s instead of `float64`.
31+
dec.UseNumber()
32+
33+
// Since 'out' is an interface representing a pointer, pass it to the decoder without an '&'
34+
return dec.Decode(out)
35+
}
36+
37+
func FetchKeybasePubkeys(input []string) (map[string]string, error) {
38+
client := cleanhttp.DefaultClient()
39+
if client == nil {
40+
return nil, fmt.Errorf("unable to create an http client")
41+
}
42+
43+
if len(input) == 0 {
44+
return nil, nil
45+
}
46+
47+
usernames := make([]string, 0, len(input))
48+
for _, v := range input {
49+
if strings.HasPrefix(v, kbPrefix) {
50+
usernames = append(usernames, strings.TrimSuffix(strings.TrimPrefix(v, kbPrefix), "\n"))
51+
}
52+
}
53+
54+
if len(usernames) == 0 {
55+
return nil, nil
56+
}
57+
58+
ret := make(map[string]string, len(usernames))
59+
url := fmt.Sprintf("https://keybase.io/_/api/1.0/user/lookup.json?usernames=%s&fields=public_keys", strings.Join(usernames, ","))
60+
resp, err := client.Get(url)
61+
if err != nil {
62+
return nil, err
63+
}
64+
defer resp.Body.Close()
65+
66+
type PublicKeys struct {
67+
Primary struct {
68+
Bundle string
69+
}
70+
}
71+
72+
type LThem struct {
73+
PublicKeys `json:"public_keys"`
74+
}
75+
76+
type KbResp struct {
77+
Status struct {
78+
Name string
79+
}
80+
Them []LThem
81+
}
82+
83+
out := &KbResp{
84+
Them: []LThem{},
85+
}
86+
87+
if err := DecodeJSONFromReader(resp.Body, out); err != nil {
88+
return nil, err
89+
}
90+
91+
if out.Status.Name != "OK" {
92+
return nil, fmt.Errorf("got non-OK response: %q", out.Status.Name)
93+
}
94+
95+
missingNames := make([]string, 0, len(usernames))
96+
var keyReader *bytes.Reader
97+
serializedEntity := bytes.NewBuffer(nil)
98+
for i, themVal := range out.Them {
99+
if themVal.Primary.Bundle == "" {
100+
missingNames = append(missingNames, usernames[i])
101+
continue
102+
}
103+
keyReader = bytes.NewReader([]byte(themVal.Primary.Bundle))
104+
entityList, err := openpgp.ReadArmoredKeyRing(keyReader)
105+
if err != nil {
106+
return nil, err
107+
}
108+
if len(entityList) != 1 {
109+
return nil, fmt.Errorf("primary key could not be parsed for user %q", usernames[i])
110+
}
111+
if entityList[0] == nil {
112+
return nil, fmt.Errorf("primary key was nil for user %q", usernames[i])
113+
}
114+
115+
serializedEntity.Reset()
116+
err = entityList[0].Serialize(serializedEntity)
117+
if err != nil {
118+
return nil, fmt.Errorf("serializing entity for user %q: %w", usernames[i], err)
119+
}
120+
121+
// The API returns values in the same ordering requested, so this should properly match
122+
ret[kbPrefix+usernames[i]] = base64.StdEncoding.EncodeToString(serializedEntity.Bytes())
123+
}
124+
125+
if len(missingNames) > 0 {
126+
return nil, fmt.Errorf("unable to fetch keys for user(s) %q from keybase", strings.Join(missingNames, ","))
127+
}
128+
129+
return ret, nil
130+
}
131+
132+
func EncryptShares(input [][]byte, pgpKeys []string) ([]string, [][]byte, error) {
133+
if len(input) != len(pgpKeys) {
134+
return nil, nil, fmt.Errorf("mismatch between number items to encrypt and number of PGP keys")
135+
}
136+
encryptedShares := make([][]byte, 0, len(pgpKeys))
137+
entities, err := GetEntities(pgpKeys)
138+
if err != nil {
139+
return nil, nil, err
140+
}
141+
for i, entity := range entities {
142+
ctBuf := bytes.NewBuffer(nil)
143+
pt, err := openpgp.Encrypt(ctBuf, []*openpgp.Entity{entity}, nil, nil, nil)
144+
if err != nil {
145+
return nil, nil, fmt.Errorf("setting up encryption for PGP message: %w", err)
146+
}
147+
_, err = pt.Write(input[i])
148+
if err != nil {
149+
return nil, nil, fmt.Errorf("encrypting PGP message: %w", err)
150+
}
151+
pt.Close()
152+
encryptedShares = append(encryptedShares, ctBuf.Bytes())
153+
}
154+
155+
fingerprints, err := GetFingerprints(nil, entities)
156+
if err != nil {
157+
return nil, nil, err
158+
}
159+
160+
return fingerprints, encryptedShares, nil
161+
}
162+
163+
func GetFingerprints(pgpKeys []string, entities []*openpgp.Entity) ([]string, error) {
164+
if entities == nil {
165+
var err error
166+
entities, err = GetEntities(pgpKeys)
167+
168+
if err != nil {
169+
return nil, err
170+
}
171+
}
172+
ret := make([]string, 0, len(entities))
173+
for _, entity := range entities {
174+
ret = append(ret, fmt.Sprintf("%x", entity.PrimaryKey.Fingerprint))
175+
}
176+
return ret, nil
177+
}
178+
179+
func GetEntities(pgpKeys []string) ([]*openpgp.Entity, error) {
180+
ret := make([]*openpgp.Entity, 0, len(pgpKeys))
181+
for _, keystring := range pgpKeys {
182+
data, err := base64.StdEncoding.DecodeString(keystring)
183+
if err != nil {
184+
return nil, fmt.Errorf("decoding given PGP key: %w", err)
185+
}
186+
entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
187+
if err != nil {
188+
return nil, fmt.Errorf("parsing given PGP key: %w", err)
189+
}
190+
ret = append(ret, entity)
191+
}
192+
return ret, nil
193+
}

tencentcloud/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ Cloud Access Management(CAM)
234234
tencentcloud_cam_role_sso
235235
tencentcloud_cam_service_linked_role
236236
tencentcloud_cam_mfa_flag
237+
tencentcloud_cam_access_key
237238
tencentcloud_cam_user_saml_config
238239
tencentcloud_cam_user_permission_boundary_attachment
239240
@@ -2707,6 +2708,7 @@ func Provider() *schema.Provider {
27072708
"tencentcloud_cam_saml_provider": resourceTencentCloudCamSAMLProvider(),
27082709
"tencentcloud_cam_service_linked_role": resourceTencentCloudCamServiceLinkedRole(),
27092710
"tencentcloud_cam_mfa_flag": resourceTencentCloudCamMfaFlag(),
2711+
"tencentcloud_cam_access_key": resourceTencentCloudCamAccessKey(),
27102712
"tencentcloud_cam_user_saml_config": resourceTencentCloudCamUserSamlConfig(),
27112713
"tencentcloud_cam_user_permission_boundary_attachment": resourceTencentCloudCamUserPermissionBoundaryAttachment(),
27122714
"tencentcloud_ciam_user_group": resourceTencentCloudCiamUserGroup(),

0 commit comments

Comments
 (0)