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

Add Permitted IPs to Access Keys #449

Merged
merged 1 commit into from
Jul 18, 2024
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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -930,12 +930,14 @@ You can create, update, delete or load access keys, as well as search according
// on a per-tenant basis.
// If userID is supplied, then authorization would be ignored, and access key would be bound to the users authorization
// If customClaims is supplied, then those claims will be present in the JWT returned by calls to ExchangeAccessKey.
// If permittedIps is supplied, then we will only allow using the access key from those IP addresses or CIDR ranges.
res, err := descopeClient.Management.AccessKey().Create(context.Background(), "access-key-1", 0, nil, []*descope.AssociatedTenant{
{TenantID: "tenant-ID1", RoleNames: []string{"role-name1"}},
{TenantID: "tenant-ID2"},
},
"",
map[string]any{"k1": "v1"})
map[string]any{"k1": "v1"},
nil)

// Load specific access key
res, err := descopeClient.Management.AccessKey().Load(context.Background(), "access-key-id")
Expand Down Expand Up @@ -1279,7 +1281,7 @@ if err == nil {
You can also create audit event with data

```go
err := descopeClient.Management.Audit().CreateEvent(context.Background(), &descope.AuditCreateOptions{
err := descopeClient.Management.Audit().CreateEvent(context.Background(), &descope.AuditCreateOptions{
Action: "pencil.created",
Type: "info", // info/warn/error
ActorID: "UXXX",
Expand Down
7 changes: 4 additions & 3 deletions descope/internal/mgmt/accesskey.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ type accessKey struct {
managementBase
}

func (a *accessKey) Create(ctx context.Context, name string, expireTime int64, roleNames []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any) (string, *descope.AccessKeyResponse, error) {
func (a *accessKey) Create(ctx context.Context, name string, expireTime int64, roleNames []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any, permittedIps []string) (string, *descope.AccessKeyResponse, error) {
if name == "" {
return "", nil, utils.NewInvalidArgumentError("name")
}
body := makeCreateAccessKeyBody(name, expireTime, roleNames, keyTenants, userID, customClaims)
body := makeCreateAccessKeyBody(name, expireTime, roleNames, keyTenants, userID, customClaims, permittedIps)
res, err := a.client.DoPostRequest(ctx, api.Routes.ManagementAccessKeyCreate(), body, nil, a.conf.ManagementKey)
if err != nil {
return "", nil, err
Expand Down Expand Up @@ -89,14 +89,15 @@ func (a *accessKey) Delete(ctx context.Context, id string) error {
return err
}

func makeCreateAccessKeyBody(name string, expireTime int64, roleNames []string, tenants []*descope.AssociatedTenant, userID string, customClaims map[string]any) map[string]any {
func makeCreateAccessKeyBody(name string, expireTime int64, roleNames []string, tenants []*descope.AssociatedTenant, userID string, customClaims map[string]any, permittedIps []string) map[string]any {
return map[string]any{
"name": name,
"expireTime": expireTime,
"roleNames": roleNames,
"keyTenants": makeAssociatedTenantList(tenants),
"userId": userID,
"customClaims": customClaims,
"permittedIps": permittedIps,
}
}

Expand Down
8 changes: 6 additions & 2 deletions descope/internal/mgmt/accesskey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func TestAccessKeyCreateSuccess(t *testing.T) {
"key": map[string]any{
"name": "abc",
"customClaims": map[string]any{"k1": "v1"},
"permittedIps": []string{"10.0.0.1"},
}}
mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
Expand All @@ -27,9 +28,12 @@ func TestAccessKeyCreateSuccess(t *testing.T) {
require.Len(t, roleNames, 1)
require.Equal(t, "foo", roleNames[0])
require.Len(t, req["customClaims"], 1)
permittedIps := req["permittedIps"].([]any)
require.Len(t, permittedIps, 1)
require.Equal(t, "10.0.0.1", permittedIps[0])
}, response))
cc := map[string]any{"k1": "v1"}
cleartext, key, err := mgmt.AccessKey().Create(context.Background(), "abc", 0, []string{"foo"}, nil, "uid", cc)
cleartext, key, err := mgmt.AccessKey().Create(context.Background(), "abc", 0, []string{"foo"}, nil, "uid", cc, []string{"10.0.0.1"})
require.NoError(t, err)
require.Equal(t, "cleartext", cleartext)
require.Equal(t, "abc", key.Name)
Expand All @@ -39,7 +43,7 @@ func TestAccessKeyCreateSuccess(t *testing.T) {

func TestAccessKeyCreateError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(nil))
_, _, err := mgmt.AccessKey().Create(context.Background(), "", 0, nil, nil, "", nil)
_, _, err := mgmt.AccessKey().Create(context.Background(), "", 0, nil, nil, "", nil, nil)
require.Error(t, err)
}

Expand Down
5 changes: 4 additions & 1 deletion descope/sdk/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ type AccessKey interface {
// If userID is supplied, then authorization would be ignored, and access key would be bound to the users authorization
// The customClaims parameter is an optional map of claims and their values, and if it's provided then
// those claims will be present in the JWT returned by calls to ExchangeAccessKey.
Create(ctx context.Context, name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any) (string, *descope.AccessKeyResponse, error)
//
// The permittedIps parameter is an optional list of IP addresses or CIDR ranges that are allowed to use this access key.
// If not provided, all IPs are allowed.
Create(ctx context.Context, name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any, permittedIps []string) (string, *descope.AccessKeyResponse, error)
nmacianx marked this conversation as resolved.
Show resolved Hide resolved

// Load an existing access key.
//
Expand Down
6 changes: 3 additions & 3 deletions descope/tests/mocks/mgmt/managementmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ func (m *MockUser) History(_ context.Context, userIDs []string) ([]*descope.User
// Mock Access Key

type MockAccessKey struct {
CreateAssert func(name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any)
CreateAssert func(name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any, permittedIps []string)
CreateResponseFn func() (string, *descope.AccessKeyResponse)
CreateError error

Expand All @@ -766,9 +766,9 @@ type MockAccessKey struct {
DeleteError error
}

func (m *MockAccessKey) Create(_ context.Context, name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any) (string, *descope.AccessKeyResponse, error) {
func (m *MockAccessKey) Create(_ context.Context, name string, expireTime int64, roles []string, keyTenants []*descope.AssociatedTenant, userID string, customClaims map[string]any, permittedIps []string) (string, *descope.AccessKeyResponse, error) {
if m.CreateAssert != nil {
m.CreateAssert(name, expireTime, roles, keyTenants, userID, customClaims)
m.CreateAssert(name, expireTime, roles, keyTenants, userID, customClaims, permittedIps)
}
var cleartext string
var key *descope.AccessKeyResponse
Expand Down
1 change: 1 addition & 0 deletions descope/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ type AccessKeyResponse struct {
ClientID string `json:"clientId,omitempty"`
UserID string `json:"boundUserId,omitempty"`
CustomClaims map[string]any `json:"customClaims,omitempty"`
PermittedIps []string `json:"permittedIps,omitempty"`
}

// Represents a tenant association for a User or an Access Key. The tenant ID is required
Expand Down
Loading