Skip to content

Commit

Permalink
初始化tencentcloud-vault开源代码,以后腾讯云国际站维护
Browse files Browse the repository at this point in the history
  • Loading branch information
firingLi committed Dec 14, 2021
1 parent 4bd1b2f commit bcf190d
Show file tree
Hide file tree
Showing 45 changed files with 2,614 additions and 2,510 deletions.
373 changes: 0 additions & 373 deletions LICENSE

This file was deleted.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ EXTERNAL_TOOLS=\
BUILD_TAGS?=${TOOL}
GOFMT_FILES?=$$(find . -name '*.go' | grep -v vendor)

# bin generates the releasable binaries for this plugin
# bin generates the releaseable binaries for this plugin
bin: fmtcheck generate
@CGO_ENABLED=0 BUILD_TAGS='$(BUILD_TAGS)' sh -c "'$(CURDIR)/scripts/build.sh'"

Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ To run the acceptance tests, you will need a TencentCloud account.
To run the acceptance tests, invoke `make test-acc`:

```sh
$ export VAULT_ACC_TEST_ACCESS_KEY=YOU ACCESS KEY
$ export VAULT_ACC_TEST_SECRET_ID=YOU
$ export VAULT_ACC_TEST_SECRET_KEY=YOU SECRET KEY
$ export VAULT_ACC_TEST_SECRET_TOKEN=YOU SECRET TOKEN (if you run as a CAM role, VAULT_ACC_TEST_SECRET_TOKEN is required)
$ export VAULT_ACC_TEST_REGION=YOU REGION
$ export VAULT_ACC_TEST_TOKEN=YOU SECRET TOKEN (if you run as a CAM role, VAULT_ACC_TEST_TOKEN is required)
$ export CLIENT_CONFIG_TEST_SECRET_ID=CLIENT CONFIG SECRET ID
$ export CLIENT_CONFIG_TEST_SECRET_KEY=CLIENT CONFIG SECRET KEY
$ make test-acc
```

Expand All @@ -121,4 +122,4 @@ You can also specify a `TESTARGS` variable to filter tests like so:

```sh
$ make test TESTARGS='--run=TestConfig'
```
```
114 changes: 114 additions & 0 deletions arn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package vault_plugin_auth_tencentcloud

import (
"errors"
"fmt"
"strings"
)

const (
arnRoleType arnType = iota // roleName
arnAssumedRoleType // assumed-role
)

const (
roleName = "roleName"
assumedRole = "assumed-role"
)

type arnType int

// toString
func (t arnType) String() string {
switch t {
case arnRoleType:
return roleName
case arnAssumedRoleType:
return assumedRole
default:
return ""
}
}

type arn struct {
Uin string
RoleName string
RoleId string
Full string
Type arnType
}

// check member
func (a *arn) IsMemberOf(possibleParent *arn) bool {
if possibleParent.Type != arnRoleType && possibleParent.Type != arnAssumedRoleType {
return false
}
if possibleParent.Uin != a.Uin {
return false
}
if possibleParent.RoleName != a.RoleName {
return false
}
return true
}

func parseARN(a string) (*arn, error) {
// camArn should look like one of the following:
// 1. qcs::cam::uin/<uin>:roleName/<RoleName>
// 2. qcs::sts:<uin>:assumed-role/<RoleId>
// if we get something like 2, then we want to transform that back to what
// most people would expect, which is qcs::cam::uin/<uin>:roleName/<RoleName>
if a == "" {
return nil, fmt.Errorf("no arn provided")
}
parsed := &arn{
Full: a,
}
outerFields := strings.Split(a, ":")
if len(outerFields) != 6 && len(outerFields) != 5 {
return nil, fmt.Errorf("unrecognized arn: contains %d colon-separated fields, expected 6 or 5", len(outerFields))
}
if outerFields[0] != "qcs" {
return nil, errors.New(`unrecognized arn: does not begin with "qcs:"`)
}
if outerFields[2] != "cam" && outerFields[2] != "sts" {
return nil, fmt.Errorf("unrecognized service: %v, not cam or sts", outerFields[2])
}
if outerFields[2] == "cam" {
uinFields := strings.Split(outerFields[4], "/")
if len(uinFields) < 2 {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated uinFields", outerFields[4])
}
parsed.Uin = uinFields[1]
roleFiles := strings.Split(outerFields[5], "/")
if len(roleFiles) == 2 {
parsed.Type = arnRoleType
if roleFiles[0] == roleName {
parsed.RoleName = roleFiles[1]
} else {
return nil, errors.New("the caller's arn does not match the role's arn")
}
} else {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated roleFiles", outerFields[4])
}
} else if outerFields[2] == "sts" {
parsed.Uin = outerFields[3]
roleFiles := strings.Split(outerFields[4], "/")
if len(roleFiles) == 2 {
parsed.Type = arnAssumedRoleType
if roleFiles[0] == assumedRole {
parsed.RoleId = roleFiles[1]
} else {
return nil, errors.New("the caller's arn does not match the role's arn")
}
} else {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated roleFiles", outerFields[4])
}
}
return parsed, nil
}

// toString
func (a *arn) String() string {
return a.Full
}
55 changes: 55 additions & 0 deletions arn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package vault_plugin_auth_tencentcloud

import (
"testing"
)

func TestParseRoleArn(t *testing.T) {
// qcs::cam::uin/100021543***:roleName/****
arn := "qcs::cam::uin/1000215438890:roleName/elk"
result, err := parseARN(arn)
if err != nil {
t.Fatal(err)
}
if result.Uin != "1000215438890" {
t.Fatalf("got %s but expected %s", result.Uin, "1000215438890")
}
if result.Type != arnRoleType {
t.Fatalf("got %d but expected %d", result.Type, arnRoleType)
}
if result.RoleName != "elk" {
t.Fatalf("got %s but wanted %s", result.RoleName, "elk")
}
if result.RoleId != "" {
t.Fatalf("got %s but wanted %s", result.RoleId, "")
}
}

func TestParseAssumedRoleArn(t *testing.T) {
// qcs::sts:1000262***:assumed-role/461168601842741***
arn := "qcs::sts:1000215438890:assumed-role/4611686018427418890"
result, err := parseARN(arn)
if err != nil {
panic(err)
}
if result.Uin != "1000215438890" {
t.Fatalf("got %s but expected %s", result.Uin, "1000215438890")
}
if result.Type != arnAssumedRoleType {
t.Fatalf("got %d but expected %d", result.Type, arnAssumedRoleType)
}
if result.RoleName != "" {
t.Fatalf("got %s but wanted %s", result.RoleName, "")
}
if result.RoleId != "4611686018427418890" {
t.Fatalf("got %s but wanted %s", result.RoleId, "4611686018427418890")
}
}

func TestParseEmpty(t *testing.T) {
arn := ""
_, err := parseARN(arn)
if err == nil {
t.Fatal("expected an err")
}
}
35 changes: 13 additions & 22 deletions plugin/backend.go → backend.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,31 @@
package plugin
package vault_plugin_auth_tencentcloud

import (
"context"
"net/http"
"os"
"strings"

"github.com/hashicorp/vault-plugin-auth-tencentcloud/sdk"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)

// Factory
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
debug := conf.Logger.IsDebug()

if !debug {
env := strings.ToLower(os.Getenv("VAULT_LOG_LEVEL"))
debug = env == "trace" || env == "debug"
client := cleanhttp.DefaultClient()
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}

b := newBackend(&sdk.LogRoundTripper{
Debug: debug,
})

b := newBackend(client)
if err := b.Setup(ctx, conf); err != nil {
return nil, err
}

return b, nil
}

func newBackend(transport http.RoundTripper) *backend {
func newBackend(client *http.Client) *backend {
b := &backend{
transport: transport,
identityClient: client,
}

b.Backend = &framework.Backend{
AuthRenew: b.pathLoginRenew,
Help: backendHelp,
Expand All @@ -45,21 +36,21 @@ func newBackend(transport http.RoundTripper) *backend {
},
Paths: []*framework.Path{
pathLogin(b),
pathListRole(b),
pathListRoles(b),
pathRole(b),
pathConfigClient(b),
},
BackendType: logical.TypeCredential,
}

return b
}

type backend struct {
*framework.Backend

transport http.RoundTripper
identityClient *http.Client
}

const backendHelp = `
That TencentCloud CAM auth method allows entities to authenticate based on their identity and pre-configured roles.
`
Loading

0 comments on commit bcf190d

Please sign in to comment.