Skip to content

Commit

Permalink
Merge pull request trustbloc#46 from llorllale/20
Browse files Browse the repository at this point in the history
feat: trustbloc#20 bootstrap data retrieve endpoint
  • Loading branch information
George Aristy committed Jul 30, 2020
2 parents 39dba44 + 7030bb1 commit 439e45a
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 23 deletions.
74 changes: 60 additions & 14 deletions cmd/auth-rest/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,19 @@ const (
googleClientSecretEnvKey = "AUTH_REST_GOOGLE_CLIENTSECRET" // nolint:gosec
)

// Bootstrap parameters.
const (
sdsURLFlagName = "sds-url"
sdsURLFlagUsage = "URL for the Secure Data Storage service." +
" Alternatively, this can be set with the following environment variable: " + sdsURLEnvKey
sdsURLEnvKey = "AUTH_REST_SDS_URL"

keyServerURLFlagName = "ks-url"
keyServerURLFlagUsage = "URL for the Key Server." +
" Alternatively, this can be set with the following environment variable: " + keyServerURLEnvKey
keyServerURLEnvKey = "AUTH_REST_KEYSERVER_URL"
)

const (
// api
healthCheckEndpoint = "/healthcheck"
Expand All @@ -122,13 +135,14 @@ const (
var logger = log.New("auth-rest")

type authRestParameters struct {
hostURL string
logLevel string
databaseType string
databaseURL string
databasePrefix string
tlsParams *tlsParams
oidcParams *oidcParams
hostURL string
logLevel string
databaseType string
databaseURL string
databasePrefix string
tlsParams *tlsParams
oidcParams *oidcParams
bootstrapParams *bootstrapParams
}

type tlsParams struct {
Expand All @@ -149,6 +163,11 @@ type oidcProviderParams struct {
clientSecret string
}

type bootstrapParams struct {
sdsURL string
keyServerURL string
}

type healthCheckResp struct {
Status string `json:"status"`
CurrentTime time.Time `json:"currentTime"`
Expand Down Expand Up @@ -233,14 +252,20 @@ func getAuthRestParameters(cmd *cobra.Command) (*authRestParameters, error) {
return nil, err
}

bootstrapParams, err := getBootstrapParams(cmd)
if err != nil {
return nil, err
}

return &authRestParameters{
hostURL: hostURL,
tlsParams: tlsParams,
logLevel: loggingLevel,
databaseType: databaseType,
databaseURL: databaseURL,
databasePrefix: databasePrefix,
oidcParams: oidcParams,
hostURL: hostURL,
tlsParams: tlsParams,
logLevel: loggingLevel,
databaseType: databaseType,
databaseURL: databaseURL,
databasePrefix: databasePrefix,
oidcParams: oidcParams,
bootstrapParams: bootstrapParams,
}, nil
}

Expand Down Expand Up @@ -293,6 +318,8 @@ func createFlags(startCmd *cobra.Command) {
startCmd.Flags().StringP(googleProviderFlagName, "", "", googleProviderFlagUsage)
startCmd.Flags().StringP(googleClientIDFlagName, "", "", googleClientIDFlagUsage)
startCmd.Flags().StringP(googleClientSecretFlagName, "", "", googleClientSecretFlagUsage)
startCmd.Flags().StringP(sdsURLFlagName, "", "", sdsURLFlagUsage)
startCmd.Flags().StringP(keyServerURLFlagName, "", "", keyServerURLFlagUsage)
}

func startAuthService(parameters *authRestParameters, srv server) error {
Expand Down Expand Up @@ -328,6 +355,10 @@ func startAuthService(parameters *authRestParameters, srv server) error {
OIDCProviderURL: parameters.oidcParams.google.providerURL,
OIDCClientID: parameters.oidcParams.google.clientID,
OIDCClientSecret: parameters.oidcParams.google.clientSecret,
BootstrapConfig: &operation.BootstrapConfig{
SDSURL: parameters.bootstrapParams.sdsURL,
KeyServerURL: parameters.bootstrapParams.keyServerURL,
},
})
if err != nil {
return err
Expand Down Expand Up @@ -391,6 +422,21 @@ func getGoogleOIDCParams(cmd *cobra.Command) (*oidcProviderParams, error) {
return params, err
}

func getBootstrapParams(cmd *cobra.Command) (*bootstrapParams, error) {
params := &bootstrapParams{}

var err error

params.sdsURL, err = cmdutils.GetUserSetVarFromString(cmd, sdsURLFlagName, sdsURLEnvKey, false)
if err != nil {
return nil, err
}

params.keyServerURL, err = cmdutils.GetUserSetVarFromString(cmd, keyServerURLFlagName, keyServerURLEnvKey, false)

return params, err
}

func setDefaultLogLevel(userLogLevel string) {
logLevel, err := log.ParseLevel(userLogLevel)
if err != nil {
Expand Down
60 changes: 60 additions & 0 deletions cmd/auth-rest/startcmd/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,52 @@ func TestStartCmdWithMissingArg(t *testing.T) {
"Neither host-url (command line flag) nor AUTH_REST_HOST_URL (environment variable) have been set.",
err.Error())
})

t.Run("missing sds url arg", func(t *testing.T) {
oidcURL := mockOIDCProvider(t)
startCmd := GetStartCmd(&mockServer{})

args := []string{
"--" + hostURLFlagName, "localhost:8080",
"--" + logLevelFlagName, log.ParseString(log.DEBUG),
"--" + databaseTypeFlagName, "mem",
"--" + oidcCallbackURLFlagName, "http://example.com/oauth2/callback",
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

err := startCmd.Execute()

require.Error(t, err)
require.Contains(t, err.Error(), sdsURLFlagName)
require.Contains(t, err.Error(), sdsURLEnvKey)
})

t.Run("missing keyserver url arg", func(t *testing.T) {
oidcURL := mockOIDCProvider(t)
startCmd := GetStartCmd(&mockServer{})

args := []string{
"--" + hostURLFlagName, "localhost:8080",
"--" + logLevelFlagName, log.ParseString(log.DEBUG),
"--" + databaseTypeFlagName, "mem",
"--" + oidcCallbackURLFlagName, "http://example.com/oauth2/callback",
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + sdsURLFlagName, "http://sds.example.com",
}
startCmd.SetArgs(args)

err := startCmd.Execute()

require.Error(t, err)
require.Contains(t, err.Error(), keyServerURLFlagName)
require.Contains(t, err.Error(), keyServerURLEnvKey)
})
}

func TestStartCmdWithBlankEnvVar(t *testing.T) {
Expand Down Expand Up @@ -164,6 +210,8 @@ func TestStartCmdValidArgs(t *testing.T) {
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + sdsURLFlagName, "http://sds.example.com",
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

Expand All @@ -185,6 +233,8 @@ func TestStartCmdValidArgs(t *testing.T) {
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + logLevelFlagName, "INVALID",
"--" + sdsURLFlagName, "http://sds.example.com",
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

Expand All @@ -207,6 +257,8 @@ func TestStartCmdValidArgs(t *testing.T) {
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + sdsURLFlagName, "http://sds.example.com",
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

Expand All @@ -231,6 +283,8 @@ func TestStartCmdFailToCreateController(t *testing.T) {
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + sdsURLFlagName, "http://sds.example.com",
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

Expand All @@ -257,6 +311,8 @@ func TestStartCmdInvalidDatabaseType(t *testing.T) {
"--" + googleProviderFlagName, oidcURL,
"--" + googleClientIDFlagName, uuid.New().String(),
"--" + googleClientSecretFlagName, uuid.New().String(),
"--" + sdsURLFlagName, "http://sds.example.com",
"--" + keyServerURLFlagName, "http://keyserver.example.com",
}
startCmd.SetArgs(args)

Expand Down Expand Up @@ -332,6 +388,10 @@ func setEnvVars(t *testing.T) {
require.NoError(t, err)
err = os.Setenv(googleClientSecretEnvKey, uuid.New().String())
require.NoError(t, err)
err = os.Setenv(sdsURLEnvKey, "http://sds.example.com")
require.NoError(t, err)
err = os.Setenv(keyServerURLEnvKey, "http://keyserver.examepl.com")
require.NoError(t, err)
}

func unsetEnvVars(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/restapi/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestController_GetOperations(t *testing.T) {
require.NotNil(t, controller)

ops := controller.GetOperations()
require.Equal(t, 2, len(ops))
require.Equal(t, 3, len(ops))
}

func config(t *testing.T) *operation.Config {
Expand Down
18 changes: 18 additions & 0 deletions pkg/restapi/operation/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package operation

type createOIDCRequestResponse struct {
Request string `json:"request"`
}

type bootstrapData struct {
SDSURL string `json:"sdsURL"`
SDSPrimaryVaultID string `json:"sdsPrimaryVaultID"`
KeyServerURL string `json:"keyServerURL"`
KeyStoreIDs []string `json:"keyStoreIDs"`
}
57 changes: 53 additions & 4 deletions pkg/restapi/operation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ import (
)

const (
oauth2GetRequestPath = "/oauth2/request"
oauth2CallbackPath = "/oauth2/callback"
oauth2GetRequestPath = "/oauth2/request"
oauth2CallbackPath = "/oauth2/callback"
bootstrapGetRequestPath = "/bootstrap"
// api path params
scopeQueryParam = "scope"

Expand Down Expand Up @@ -117,6 +118,7 @@ type Operation struct {
oidcCallbackURL string
oauth2ConfigFunc func(...string) oauth2Config
bootstrapStore storage.Store
bootstrapConfig *BootstrapConfig
}

// Config defines configuration for rp operations.
Expand All @@ -129,10 +131,13 @@ type Config struct {
OIDCCallbackURL string
TransientStoreProvider storage.Provider
StoreProvider storage.Provider
BootstrapConfig *BootstrapConfig
}

type createOIDCRequestResponse struct {
Request string `json:"request"`
// BootstrapConfig holds user bootstrap-related config.
type BootstrapConfig struct {
SDSURL string
KeyServerURL string
}

// New returns rp operation instance.
Expand All @@ -143,6 +148,7 @@ func New(config *Config) (*Operation, error) {
oidcClientID: config.OIDCClientID,
oidcClientSecret: config.OIDCClientSecret,
oidcCallbackURL: config.OIDCCallbackURL,
bootstrapConfig: config.BootstrapConfig,
}

// TODO implement retries: https://github.com/trustbloc/hub-auth/issues/45
Expand Down Expand Up @@ -340,6 +346,48 @@ func (c *Operation) onboardUser(id string) (*user.Profile, error) {
return userProfile, nil
}

func (c *Operation) handleBootstrapDataRequest(w http.ResponseWriter, r *http.Request) {
handle := r.URL.Query().Get("up")
if handle == "" {
handleAuthError(w, http.StatusBadRequest, "missing handle")

return
}

profile, err := user.NewStore(c.transientStore).Get(handle)
if errors.Is(err, storage.ErrValueNotFound) {
handleAuthError(w, http.StatusBadRequest, "invalid handle")

return
}

if err != nil {
handleAuthError(w, http.StatusInternalServerError,
fmt.Sprintf("failed to query transient store for handle: %s", err))

return
}

response, err := json.Marshal(&bootstrapData{
SDSURL: c.bootstrapConfig.SDSURL,
SDSPrimaryVaultID: profile.SDSPrimaryVaultID,
KeyServerURL: c.bootstrapConfig.KeyServerURL,
KeyStoreIDs: profile.KeyStoreIDs,
})
if err != nil {
handleAuthError(w, http.StatusInternalServerError, fmt.Sprintf("failed to marshal bootstrap data: %s", err))

return
}

// TODO We should delete the handle from the transient store after writing the response,
// but edge-core store API doesn't have a Delete() operation: https://github.com/trustbloc/edge-core/issues/45
_, err = w.Write(response)
if err != nil {
logger.Errorf("failed to write bootstrap data to output: %s", err)
}
}

// TODO redirect to the UI: https://github.com/trustbloc/hub-auth/issues/39
func handleAuthResult(w http.ResponseWriter, r *http.Request, _ *user.Profile) {
http.Redirect(w, r, "", http.StatusFound)
Expand Down Expand Up @@ -373,6 +421,7 @@ func (c *Operation) GetRESTHandlers() []Handler {
return []Handler{
support.NewHTTPHandler(oauth2GetRequestPath, http.MethodGet, c.createOIDCRequest),
support.NewHTTPHandler(oauth2CallbackPath, http.MethodGet, c.handleOIDCCallback),
support.NewHTTPHandler(bootstrapGetRequestPath, http.MethodGet, c.handleBootstrapDataRequest),
}
}

Expand Down
Loading

0 comments on commit 439e45a

Please sign in to comment.