Skip to content
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
76 changes: 59 additions & 17 deletions app/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const (
caCertificateFingerprintFlagName = "ca-certificate-fingerprint"
searchAttributeFlagName = "search-attribute"
userNamespacePermissionFlagName = "user-namespace-permission"
codecEndpointFlagName = "endpoint"
codecPassAccessTokenFlagName = "pass-access-token"
codecIncludeCredentialsFlagName = "include-credentials"
)

var (
Expand Down Expand Up @@ -79,7 +82,6 @@ var (
Name: "kms-arn",
Usage: "Provide the ARN of the KMS key to use for encryption. Note: If the KMS ARN needs to be added or updated, user should create the IAM Role with KMS or modify the created IAM Role accordingly. Provided it as part of the input won't help",
}

pageSizeFlag = &cli.IntFlag{
Name: "page-size",
Usage: "The page size for list operations",
Expand All @@ -89,6 +91,21 @@ var (
Name: "page-token",
Usage: "The page token for list operations",
}
codecIncludeCredentialsFlag = &cli.BoolFlag{
Name: codecIncludeCredentialsFlagName,
Usage: "Include cross-origin credentials",
Aliases: []string{"ic"},
}
codecPassAccessTokenFlag = &cli.BoolFlag{
Name: codecPassAccessTokenFlagName,
Usage: "Pass the user access token to the remote endpoint",
Aliases: []string{"pat"},
}
codecEndpointFlag = &cli.StringFlag{
Name: codecEndpointFlagName,
Usage: "The codec server endpoint to decode payloads for all users interacting with this Namespace, must be https",
Aliases: []string{"e"},
}
)

type NamespaceClient struct {
Expand Down Expand Up @@ -429,6 +446,9 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
Usage: fmt.Sprintf("Flag can be used multiple times; value must be \"email=permission\"; valid permissions are: %v", getNamespacePermissionTypes()),
Aliases: []string{"p"},
},
codecEndpointFlag,
codecPassAccessTokenFlag,
codecIncludeCredentialsFlag,
},
Action: func(ctx *cli.Context) error {
n := &namespace.Namespace{
Expand Down Expand Up @@ -500,6 +520,24 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
}
}

codecEndpoint := ctx.String(codecEndpointFlagName)
// codec server spec is optional, if specified, we need to create the spec and pass along to the API
if codecEndpoint != "" {
err = validateCodecEndpoint(codecEndpoint)
if err != nil {
return err
}
n.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
Endpoint: codecEndpoint,
PassAccessToken: ctx.Bool(codecPassAccessTokenFlagName),
Comment thread
mastermanu marked this conversation as resolved.
IncludeCredentials: ctx.Bool(codecIncludeCredentialsFlagName),
}
} else {
if ctx.Bool(codecPassAccessTokenFlagName) || ctx.Bool(codecIncludeCredentialsFlagName) {
return errors.New("pass-access-token or include-credentials cannot be specified when codec endpoint is not specified")
}
}

return c.createNamespace(n, unp)
},
},
Expand Down Expand Up @@ -936,32 +974,29 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
Flags: []cli.Flag{
NamespaceFlag,
&cli.StringFlag{
Name: "endpoint",
Usage: "The codec server endpoint to decode payloads for all users interacting with this Namespace, must be https",
Aliases: []string{"e"},
Name: codecEndpointFlag.Name,
Usage: codecEndpointFlag.Usage,
Aliases: codecEndpointFlag.Aliases,
Required: true,
},
&cli.BoolFlag{
Name: "pass-access-token",
Usage: "Pass the user access token with the remote endpoint",
Aliases: []string{"pat"},
},
&cli.BoolFlag{
Name: "include-credentials",
Usage: "Include cross-origin credentials",
Aliases: []string{"ic"},
},
codecPassAccessTokenFlag,
codecIncludeCredentialsFlag,
},
Action: func(ctx *cli.Context) error {
n, err := c.getNamespace(ctx.String(NamespaceFlagName))
if err != nil {
return err
}

codecEndpoint := ctx.String(codecEndpointFlagName)
err = validateCodecEndpoint(codecEndpoint)
if err != nil {
return err
}
replacement := &namespace.CodecServerPropertySpec{
Endpoint: ctx.String("endpoint"),
PassAccessToken: ctx.Bool("pass-access-token"),
IncludeCredentials: ctx.Bool("include-credentials"),
Endpoint: codecEndpoint,
PassAccessToken: ctx.Bool(codecPassAccessTokenFlagName),
IncludeCredentials: ctx.Bool(codecIncludeCredentialsFlagName),
}

difference, err := compareCodecSpec(n.Spec.CodecSpec, replacement)
Expand Down Expand Up @@ -1395,6 +1430,13 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
return CommandOut{Command: command}, nil
}

func validateCodecEndpoint(codecEndpoint string) error {
if !strings.HasPrefix(codecEndpoint, "https://") {
return errors.New("field Endpoint has to use https")
}
return nil
}

func getSearchAttributeTypes() []string {
validTypes := []string{}
for i := 1; i < len(namespace.SearchAttributeType_name); i++ {
Expand Down
62 changes: 56 additions & 6 deletions app/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1095,28 +1095,28 @@ func (s *NamespaceTestSuite) TestUpdateCodecServer() {
expectErr: true,
},
{
args: []string{"n", "ucs", "-n", ns, "-endpoint", "fakehost:9999"},
args: []string{"n", "ucs", "-n", ns, "-endpoint", "https://fakehost:9999"},
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{Endpoint: "fakehost:9999"}
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{Endpoint: "https://fakehost:9999"}
},
},
{
args: []string{"n", "ucs", "-n", ns, "-e", "fakehost:9999", "--pass-access-token"},
args: []string{"n", "ucs", "-n", ns, "-e", "https://fakehost:9999", "--pass-access-token"},
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
Endpoint: "fakehost:9999",
Endpoint: "https://fakehost:9999",
PassAccessToken: true,
}
},
},
{
args: []string{"n", "ucs", "-n", ns, "-e", "fakehost:9999", "--pat", "--include-credentials"},
args: []string{"n", "ucs", "-n", ns, "-e", "https://fakehost:9999", "--pat", "--include-credentials"},
expectGet: func(g *namespaceservice.GetNamespaceResponse) {},
expectUpdate: func(r *namespaceservice.UpdateNamespaceRequest) {
r.Spec.CodecSpec = &namespace.CodecServerPropertySpec{
Endpoint: "fakehost:9999",
Endpoint: "https://fakehost:9999",
PassAccessToken: true,
IncludeCredentials: true,
}
Expand Down Expand Up @@ -1397,6 +1397,56 @@ func (s *NamespaceTestSuite) TestCreate() {
))
}

func (s *NamespaceTestSuite) TestCreateWithCodec() {
s.mockService.EXPECT().CreateNamespace(gomock.Any(), gomock.Any()).Return(&namespaceservice.CreateNamespaceResponse{
RequestStatus: &request.RequestStatus{},
}, nil).AnyTimes()
s.mockAuthService.EXPECT().GetUser(gomock.Any(), gomock.Any()).Return(&authservice.GetUserResponse{
User: &auth.User{
Id: "test-user-id",
Spec: &auth.UserSpec{
Email: "testuser@testcompany.com",
},
},
}, nil).AnyTimes()
s.NoError(s.RunCmd(
"namespace", "create",
"--namespace", "ns1",
"--region", "us-west-2",
"--ca-certificate", "cert1",
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
"--search-attribute", "testsearchattribute=Keyword",
"--user-namespace-permission", "testuser@testcompany.com=Read",
"--endpoint", "https://test-endpoint.com", "--pass-access-token", "--include-credentials", "false",
))

err := s.RunCmd(
"namespace", "create",
"--namespace", "ns1",
"--region", "us-west-2",
"--ca-certificate", "cert1",
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
"--search-attribute", "testsearchattribute=Keyword",
"--user-namespace-permission", "testuser@testcompany.com=Read",
"--endpoint", "http://test-endpoint.com", "--pass-access-token",
)
s.Error(err)
s.ErrorContains(err, "field Endpoint has to use https")

err = s.RunCmd(
"namespace", "create",
"--namespace", "ns1",
"--region", "us-west-2",
"--ca-certificate", "cert1",
"--certificate-filter-input", "{ \"filters\": [ { \"commonName\": \"test1\" } ] }",
"--search-attribute", "testsearchattribute=Keyword",
"--user-namespace-permission", "testuser@testcompany.com=Read",
"--pass-access-token",
)
s.Error(err)
s.ErrorContains(err, "pass-access-token or include-credentials cannot be specified when codec endpoint is not specified")
}

func (s *NamespaceTestSuite) TestDelete() {
s.Error(s.RunCmd("namespace", "delete"))
s.mockService.EXPECT().GetNamespace(gomock.Any(), gomock.Any()).Return(&namespaceservice.GetNamespaceResponse{
Expand Down