Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.

Commit f9c0186

Browse files
Merge pull request #219 from secrethub/release/v0.31.0
Release v0.31.0
2 parents 9cc9510 + be64d87 commit f9c0186

File tree

15 files changed

+287
-18
lines changed

15 files changed

+287
-18
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<i>Go Client</i>
88
</h1>
99

10-
[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)][godoc]
10+
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)][godoc]
1111
[![CircleCI](https://circleci.com/gh/secrethub/secrethub-go.svg?style=shield)][circle-ci]
1212
[![Go Report Card](https://goreportcard.com/badge/github.com/secrethub/secrethub-go)][goreportcard]
1313
[![Version]( https://img.shields.io/github/release/secrethub/secrethub-go.svg)][latest-version]
@@ -148,7 +148,7 @@ If you get stuck or just want advice, come chat with the engineers on [Discord][
148148
[latest-version]: https://github.com/secrethub/secrethub-go/releases/latest
149149
[issues]: https://github.com/secrethub/secrethub-go/issues/new
150150
[pulls]: https://github.com/secrethub/secrethub-go/pulls
151-
[godoc]: http://godoc.org/github.com/secrethub/secrethub-go
151+
[godoc]: https://pkg.go.dev/github.com/secrethub/secrethub-go?tab=overview
152152
[goreportcard]: https://goreportcard.com/report/github.com/secrethub/secrethub-go
153153
[circle-ci]: https://circleci.com/gh/secrethub/secrethub-go
154154
[discord]: https://discord.gg/EQcE87s

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
1818
google.golang.org/api v0.26.0
1919
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940
20+
google.golang.org/grpc v1.28.0
2021
)
2122

2223
go 1.13

internals/api/patterns.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var (
3939
whitelistOrgName = regexp.MustCompile(fmt.Sprintf(`(?i)^(%s{%d,%d})$`, patternUniformNameCharacters, uniformNameMinimumLength, uniformNameMaximumLength))
4040
whitelistFullName = regexp.MustCompile(fmt.Sprintf(`(?i)^(%s{1,128})$`, patternFullName))
4141
whitelistDescription = regexp.MustCompile(fmt.Sprintf(`(?i)^(%s)$`, patternDescription))
42+
whitelistSetupCode = regexp.MustCompile("^su-[a-zA-Z0-9-]{8,64}")
4243

4344
whitelistAtLeastOneAlphanumeric = regexp.MustCompile(fmt.Sprintf("%s{1,}", patternAlphanumeric))
4445

@@ -89,6 +90,7 @@ var (
8990
ErrInvalidGCPServiceAccountEmail = errAPI.Code("invalid_service_account_email").StatusError("not a valid GCP service account email", http.StatusBadRequest)
9091
ErrNotUserManagerGCPServiceAccountEmail = errAPI.Code("require_user_managed_service_account").StatusError("provided GCP service account email is not for a user-manager service account", http.StatusBadRequest)
9192
ErrInvalidGCPKMSResourceID = errAPI.Code("invalid_key_resource_id").StatusError("not a valid resource ID, expected: projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY", http.StatusBadRequest)
93+
ErrInvalidSetupCode = errAPI.Code("invalid_setup_code").StatusError("setup code starts with su- and is followed by groups of letters and numbers separated by dashes", http.StatusBadRequest)
9294
)
9395

9496
// ValidateNamespace validates a username.
@@ -353,3 +355,11 @@ func ValidateGCPKMSKeyResourceID(v string) error {
353355

354356
return nil
355357
}
358+
359+
// ValidateSetupCode checks whether the given string has the format of a valid setup code.
360+
func ValidateSetupCode(code string) error {
361+
if !whitelistSetupCode.MatchString(code) {
362+
return ErrInvalidSetupCode
363+
}
364+
return nil
365+
}

pkg/secrethub/account.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ var (
1414

1515
// AccountService handles operations on SecretHub accounts.
1616
type AccountService interface {
17+
// Me retrieves the authenticated account of the client.
18+
Me() (*api.Account, error)
1719
// Get retrieves an account by name.
1820
Get(name string) (*api.Account, error)
1921
// Keys returns an account key service.
@@ -30,6 +32,11 @@ type accountService struct {
3032
client *Client
3133
}
3234

35+
// Me retrieves the authenticated account of the client.
36+
func (s accountService) Me() (*api.Account, error) {
37+
return s.client.getMyAccount()
38+
}
39+
3340
// Get retrieves an account by name.
3441
func (s accountService) Get(name string) (*api.Account, error) {
3542
accountName, err := api.NewAccountName(name)

pkg/secrethub/client.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func NewClient(with ...ClientOption) (*Client, error) {
138138
}
139139

140140
// Try to use default key credentials if none provided explicitly
141-
if client.decrypter == nil {
141+
if !client.httpClient.IsAuthenticated() && client.decrypter == nil {
142142
identityProvider := os.Getenv("SECRETHUB_IDENTITY_PROVIDER")
143143

144144
var provider credentials.Provider
@@ -207,7 +207,7 @@ func (c *Client) Accounts() AccountService {
207207

208208
// Credentials returns a service used to manage credentials.
209209
func (c *Client) Credentials() CredentialService {
210-
return newCredentialService(c)
210+
return newCredentialService(c, c.httpClient.IsAuthenticated, c.isKeyed)
211211
}
212212

213213
// Dirs returns a service used to manage directories.
@@ -272,6 +272,10 @@ func (c *Client) DefaultCredential() credentials.Reader {
272272
return c.ConfigDir.Credential()
273273
}
274274

275+
func (c *Client) isKeyed() bool {
276+
return c.decrypter != nil
277+
}
278+
275279
func (c *Client) userAgent() string {
276280
userAgent := userAgentPrefix
277281
for _, info := range c.appInfo {

pkg/secrethub/client_version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ package secrethub
22

33
// ClientVersion is the current version of the client
44
// Do not edit this unless you know what you're doing.
5-
const ClientVersion = "v0.30.0"
5+
const ClientVersion = "v0.31.0"

pkg/secrethub/credentials.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package secrethub
22

33
import (
4+
"github.com/secrethub/secrethub-go/internals/crypto"
45
"github.com/secrethub/secrethub-go/pkg/secrethub/iterator"
56

67
"github.com/secrethub/secrethub-go/internals/api"
@@ -17,23 +18,42 @@ type CredentialService interface {
1718
List(_ *CredentialListParams) CredentialIterator
1819
}
1920

20-
func newCredentialService(client *Client) CredentialService {
21+
func newCredentialService(client *Client, isAuthenticated func() bool, isKeyed func() bool) CredentialService {
2122
return credentialService{
22-
client: client,
23+
client: client,
24+
isAuthenticated: isAuthenticated,
25+
isKeyed: isKeyed,
2326
}
2427
}
2528

2629
type credentialService struct {
27-
client *Client
30+
client *Client
31+
isAuthenticated func() bool
32+
isKeyed func() bool
2833
}
2934

3035
// Create a new credential from the credentials.Creator for an existing account.
31-
// This includes a re-encrypted copy the the account key.
36+
// If the account is already keyed, the key is re-encrypted for the new credential.
37+
// If the account is not yet keyed, a new account key is also created.
3238
// Description is optional and can be left empty.
3339
func (s credentialService) Create(creator credentials.Creator, description string) (*api.Credential, error) {
34-
accountKey, err := s.client.getAccountKey()
35-
if err != nil {
36-
return nil, err
40+
if !s.isAuthenticated() {
41+
return nil, ErrNoDecryptionKey
42+
}
43+
44+
var accountKey crypto.RSAPrivateKey
45+
var err error
46+
if !s.isKeyed() {
47+
accountKey, err = generateAccountKey()
48+
if err != nil {
49+
return nil, err
50+
}
51+
} else {
52+
key, err := s.client.getAccountKey()
53+
if err != nil {
54+
return nil, err
55+
}
56+
accountKey = *key
3757
}
3858

3959
err = creator.Create()
@@ -47,7 +67,7 @@ func (s credentialService) Create(creator credentials.Creator, description strin
4767
return nil, err
4868
}
4969

50-
accountKeyRequest, err := s.client.createAccountKeyRequest(creator.Encrypter(), *accountKey)
70+
accountKeyRequest, err := s.client.createAccountKeyRequest(creator.Encrypter(), accountKey)
5171
if err != nil {
5272
return nil, err
5373
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package credentials
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
httpclient "github.com/secrethub/secrethub-go/pkg/secrethub/internals/http"
8+
9+
"github.com/secrethub/secrethub-go/internals/auth"
10+
)
11+
12+
type SetupCode struct {
13+
code string
14+
}
15+
16+
// Provide implements the Provider interface for the setup code.
17+
// Note that no decrypter is ever returned as setup codes cannot be used to decrypt secrets.
18+
func (s *SetupCode) Provide(client *httpclient.Client) (auth.Authenticator, Decrypter, error) {
19+
return s, nil, nil
20+
}
21+
22+
func NewSetupCode(code string) *SetupCode {
23+
return &SetupCode{
24+
code: code,
25+
}
26+
}
27+
28+
// Authenticate authenticates the given request with a setup code, by providing the "SetupCode" tag and the setup code
29+
// in the "Authorization" header.
30+
func (s *SetupCode) Authenticate(r *http.Request) error {
31+
r.Header.Set("Authorization", fmt.Sprintf("%s-%s %s", auth.AuthHeaderVersionV1, "SetupCode", s.code))
32+
return nil
33+
}

pkg/secrethub/fakeclient/account.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
// AccountService is a mock of the AccountService interface.
1111
type AccountService struct {
12+
MeFunc func() (*api.Account, error)
1213
GetFunc func(name string) (*api.Account, error)
1314
AccountKeyService secrethub.AccountKeyService
1415
}
@@ -21,3 +22,8 @@ func (s *AccountService) Keys() secrethub.AccountKeyService {
2122
func (s *AccountService) Get(name string) (*api.Account, error) {
2223
return s.GetFunc(name)
2324
}
25+
26+
// Me implements the AccountService interface Me function.
27+
func (s *AccountService) Me() (*api.Account, error) {
28+
return s.MeFunc()
29+
}

pkg/secrethub/fakeclient/client.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@ package fakeclient
66

77
import "github.com/secrethub/secrethub-go/pkg/secrethub"
88

9+
var _ secrethub.ClientInterface = (*Client)(nil)
10+
911
// Client implements the secrethub.Client interface.
1012
type Client struct {
1113
AccessRuleService *AccessRuleService
1214
AccountService *AccountService
15+
CredentialService *CredentialService
1316
DirService *DirService
17+
IDPLinkService *IDPLinkService
18+
MeService *MeService
1419
OrgService *OrgService
1520
RepoService *RepoService
1621
SecretService *SecretService
1722
ServiceService *ServiceService
1823
UserService *UserService
19-
secrethub.ClientInterface
2024
}
2125

2226
// AccessRules implements the secrethub.Client interface.
@@ -36,7 +40,7 @@ func (c Client) Dirs() secrethub.DirService {
3640

3741
// Me implements the secrethub.Client interface.
3842
func (c Client) Me() secrethub.MeService {
39-
return nil
43+
return c.MeService
4044
}
4145

4246
// Orgs implements the secrethub.Client interface.
@@ -63,3 +67,11 @@ func (c Client) Services() secrethub.ServiceService {
6367
func (c Client) Users() secrethub.UserService {
6468
return c.UserService
6569
}
70+
71+
func (c Client) IDPLinks() secrethub.IDPLinkService {
72+
return c.IDPLinkService
73+
}
74+
75+
func (c Client) Credentials() secrethub.CredentialService {
76+
return c.CredentialService
77+
}

0 commit comments

Comments
 (0)