Skip to content

Commit

Permalink
Merge pull request #152 from sol-eng/remove-authentication-components
Browse files Browse the repository at this point in the history
Remove authentication components
  • Loading branch information
tnederlof authored Apr 29, 2023
2 parents e1c43f2 + 55d9393 commit a6190e4
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 666 deletions.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ You can also pass the `--step` flag to begin at a certain spot in the interactiv
sudo wbi setup --step workbench
```

The following steps are valid options: start, prereqs, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, auth, packagemanager, connect, restart, status, verify.
The following steps are valid options: start, prereqs, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, packagemanager, connect, restart, status, verify.

## Assumptions
- Single server
Expand Down Expand Up @@ -95,10 +95,6 @@ The following steps are valid options: start, prereqs, firewall, security, langu
### SSL
- Record and specify where to put cert and key paths

### Authentication
- Provide information about PAM and AD/LDAP setup steps
- Record and specify where to put values for SAML and OIDC SSO setups

### Posit Package Manager integration
- Record, validate, and specify config for Posit Package Manger URL and R/Python repos
- Automatically generate, validate and specify config for Posit Public Package Manager
Expand Down
104 changes: 6 additions & 98 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,10 @@ type configCmd struct {
}

type configOpts struct {
certPath string
keyPath string
url string
source string
authType string
idpURL string
usernameClaim string
clientID string
clientSecret string
certPath string
keyPath string
url string
source string
}

func newConfig(configOpts configOpts, item string) error {
Expand All @@ -33,20 +28,6 @@ func newConfig(configOpts configOpts, item string) error {
if err != nil {
return fmt.Errorf("failed to write SSL config for Workbench: %w", err)
}
} else if item == "auth" {
if configOpts.authType == "saml" {
err := workbench.WriteSAMLAuthConfig(configOpts.idpURL)
if err != nil {
return fmt.Errorf("failed to write SAML auth config for Workbench: %w", err)
}
} else if configOpts.authType == "oidc" {
err := workbench.WriteOIDCAuthConfig(configOpts.idpURL, configOpts.usernameClaim, configOpts.clientID, configOpts.clientSecret)
if err != nil {
return fmt.Errorf("failed to write OIDC auth config for Workbench: %w", err)
}
} else {
return fmt.Errorf("invalid auth type provided, please provide one of the following: saml, oidc")
}
} else if item == "repo" {
err := workbench.WriteRepoConfig(configOpts.url, configOpts.source)
if err != nil {
Expand All @@ -58,7 +39,7 @@ func newConfig(configOpts configOpts, item string) error {
return fmt.Errorf("failed to write Connect URL config for Workbench: %w", err)
}
} else {
return fmt.Errorf("invalid item provided, please provide one of the following: ssl, auth, repo, connect-url")
return fmt.Errorf("invalid item provided, please provide one of the following: ssl, repo, connect-url")
}
return nil
}
Expand All @@ -68,11 +49,6 @@ func setConfigOpts(configOpts *configOpts) {
configOpts.keyPath = viper.GetString("key-path")
configOpts.url = viper.GetString("url")
configOpts.source = viper.GetString("source")
configOpts.authType = viper.GetString("auth-type")
configOpts.idpURL = viper.GetString("idp-url")
configOpts.usernameClaim = viper.GetString("username-claim")
configOpts.clientID = viper.GetString("client-id")
configOpts.clientSecret = viper.GetString("client-secret")
}

func (opts *configOpts) Validate(args []string) error {
Expand All @@ -83,29 +59,6 @@ func (opts *configOpts) Validate(args []string) error {
return fmt.Errorf("too many arguments provided, please provide only one argument")
}

// the auth-type flag is only valid for auth
if opts.authType != "" && args[0] != "auth" {
return fmt.Errorf("the auth-type flag is only valid for auth")
}

// the idp-url flag is only valid for argument auth and auth-type saml or oidc
if opts.idpURL != "" && (args[0] != "auth" || (opts.authType != "saml" && opts.authType != "oidc")) {
return fmt.Errorf("the idp-url flag is only valid with auth as an argument and a auth-type flag of saml or oidc")
}

// the username-claim flag is only valid for argument auth and auth-type oidc
if opts.usernameClaim != "" && (args[0] != "auth" || opts.authType != "oidc") {
return fmt.Errorf("the username-claim flag is only valid with auth as an argument and a auth-type flag of oidc")
}
// the client-id flag is only valid for argument auth and auth-type oidc
if opts.clientID != "" && (args[0] != "auth" || opts.authType != "oidc") {
return fmt.Errorf("the client-id flag is only valid with auth as an argument and a auth-type flag of oidc")
}
// the client-secret flag is only valid for argument auth and auth-type oidc
if opts.clientSecret != "" && (args[0] != "auth" || opts.authType != "oidc") {
return fmt.Errorf("the client-secret flag is only valid with auth as an argument and a auth-type flag of oidc")
}

// the cert-path flag is required for ssl
if opts.certPath == "" && args[0] == "ssl" {
return fmt.Errorf("the cert-path flag is required for ssl")
Expand Down Expand Up @@ -154,30 +107,6 @@ func (opts *configOpts) Validate(args []string) error {
return fmt.Errorf("the source flag only allows cran and pypi")
}

// the auth-type flag is required for auth
if opts.authType == "" && args[0] == "auth" {
return fmt.Errorf("the auth-type flag is required for auth")
}

// the idp-url flag is required for argument auth and auth-type saml
if opts.idpURL == "" && args[0] == "auth" && (opts.authType == "saml" || opts.authType == "oidc") {
return fmt.Errorf("the idp-url flag is required for argument auth and auth-type flag of saml or odic")
}

// the client-id flag is required for argument auth and auth-type oidc
if opts.clientID == "" && args[0] == "auth" && opts.authType == "oidc" {
return fmt.Errorf("the client-id flag is required for argument auth and auth-type flag of odic")
}
// the client-secret flag is required for argument auth and auth-type oidc
if opts.clientSecret == "" && args[0] == "auth" && opts.authType == "oidc" {
return fmt.Errorf("the client-secret flag is required for argument auth and auth-type flag of odic")
}

// the only valid authType flags are saml and oidc
if args[0] == "auth" && (opts.authType != "saml" && opts.authType != "oidc") {
return fmt.Errorf("the auth-type flag only allows saml and oidc")
}

return nil
}

Expand All @@ -191,12 +120,6 @@ func newConfigCmd() *configCmd {
"To configure TLS/SSL:",
" wbi config ssl --cert-path [PATH-TO-CERTIFICATE-FILE] --key-path [PATH-TO-KEY-FILE]",
"",
"To configure SAML Authentication:",
" wbi config auth --auth-type saml --idp-url [IDP-SAML-METADATA-URL]",
"",
"To configure OIDC Authentication:",
" wbi config auth --auth-type oidc --idp-url [IDP-OIC-ISSUER-URL] --client-id [CLIENT-ID] --client-secret [CLIENT-SECRET]",
"",
"To configure a default package repository:",
" wbi config repo --url [REPO-BASE-URL] --source cran",
" wbi config repo --url [REPO-BASE-URL] --source pypi",
Expand All @@ -207,7 +130,7 @@ func newConfigCmd() *configCmd {

cmd := &cobra.Command{
Use: "config [item]",
Short: "Configure SSL, Authentication, package repos, or a Connect server in Posit Workbench",
Short: "Configure SSL, package repos, or a Connect server in Posit Workbench",
Example: strings.Join(exampleText, "\n"),
PreRunE: func(cmd *cobra.Command, args []string) error {
setConfigOpts(&root.opts)
Expand Down Expand Up @@ -238,21 +161,6 @@ func newConfigCmd() *configCmd {
cmd.Flags().StringP("source", "s", "", "Repository source (cran or pypi)")
viper.BindPFlag("source", cmd.Flags().Lookup("source"))

cmd.Flags().StringP("auth-type", "a", "", "Authentication type (saml or oidc)")
viper.BindPFlag("auth-type", cmd.Flags().Lookup("auth-type"))

cmd.Flags().StringP("idp-url", "i", "", "")
viper.BindPFlag("idp-url", cmd.Flags().Lookup("idp-url"))

cmd.Flags().StringP("username-claim", "", "", "IdP Metdata URL for SAML or OIDC")
viper.BindPFlag("username-claim", cmd.Flags().Lookup("username-claim"))

cmd.Flags().StringP("client-id", "", "", "OIDC Client ID")
viper.BindPFlag("client-id", cmd.Flags().Lookup("client-id"))

cmd.Flags().StringP("client-secret", "", "", "OIDC Client Secret")
viper.BindPFlag("client-secret", cmd.Flags().Lookup("client-secret"))

root.cmd = cmd
return root
}
154 changes: 0 additions & 154 deletions cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,82 +50,6 @@ func TestConfigParamsValidate(t *testing.T) {
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", source: "cran"},
expectError: "the source flag is only valid for repo",
},
"ssl argument with auth-type flag fails": {
args: []string{"ssl"},
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", authType: "saml"},
expectError: "the auth-type flag is only valid for auth",
},
"ssl argument with idp-url flag fails": {
args: []string{"ssl"},
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", idpURL: "https://www.example.com"},
expectError: "the idp-url flag is only valid with auth as an argument and a auth-type flag of saml or oidc",
},
"ssl argument with username-claim flag fails": {
args: []string{"ssl"},
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", usernameClaim: "user"},
expectError: "the username-claim flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"ssl argument with client-id flag fails": {
args: []string{"ssl"},
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", clientID: "user"},
expectError: "the client-id flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"ssl argument with client-secret flag fails": {
args: []string{"ssl"},
flags: configOpts{certPath: "cert.crt", keyPath: "cert.key", clientSecret: "user"},
expectError: "the client-secret flag is only valid with auth as an argument and a auth-type flag of oidc",
},
// auth argument tests
"auth argument only fails": {
args: []string{"auth"},
flags: configOpts{},
expectError: "the auth-type flag is required for auth",
},
"auth argument with the auth-type flag fails": {
args: []string{"auth"},
flags: configOpts{authType: "saml"},
expectError: "the idp-url flag is required for argument auth and auth-type flag of saml or odic",
},
"auth argument with the auth-type saml and idp-url flags set succeeds": {
args: []string{"auth"},
flags: configOpts{authType: "saml", idpURL: "https://www.example.com"},
expectError: "",
},
"auth argument with the auth-type oidc and idp-url flags set fails": {
args: []string{"auth"},
flags: configOpts{authType: "oidc", idpURL: "https://www.example.com"},
expectError: "the client-id flag is required for argument auth and auth-type flag of odic",
},
"auth argument with the auth-type oidc and idp-url and client-id flags set fails": {
args: []string{"auth"},
flags: configOpts{authType: "oidc", idpURL: "https://www.example.com", clientID: "dadawdaw"},
expectError: "the client-secret flag is required for argument auth and auth-type flag of odic",
},
"auth argument with the auth-type oidc and idp-url, client-id, and client-secret flags set succeeds": {
args: []string{"auth"},
flags: configOpts{authType: "oidc", idpURL: "https://www.example.com", clientID: "adwada", clientSecret: "adawdaw"},
expectError: "",
},
"auth argument with url flag fails": {
args: []string{"auth"},
flags: configOpts{authType: "saml", idpURL: "https://www.example.com", url: "https://www.packagemanager.rstudio.com"},
expectError: "the url flag is only valid for repo and connect-url",
},
"auth argument with source flag fails": {
args: []string{"auth"},
flags: configOpts{authType: "saml", idpURL: "https://www.example.com", source: "cran"},
expectError: "the source flag is only valid for repo",
},
"auth argument with cert-path flag fails": {
args: []string{"auth"},
flags: configOpts{authType: "saml", idpURL: "https://www.example.com", certPath: "cert.crt"},
expectError: "the cert-path flag is only valid for ssl",
},
"auth argument with key-path flag fails": {
args: []string{"auth"},
flags: configOpts{authType: "saml", idpURL: "https://www.example.com", keyPath: "cert.key"},
expectError: "the key-path flag is only valid for ssl",
},
// repo argument tests
"repo argument only fails": {
args: []string{"repo"},
Expand All @@ -147,31 +71,6 @@ func TestConfigParamsValidate(t *testing.T) {
flags: configOpts{url: "https://packagemanager.posit.co", source: "pypi"},
expectError: "",
},
"repo argument with auth-type flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", authType: "saml"},
expectError: "the auth-type flag is only valid for auth",
},
"repo argument with idp-url flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", idpURL: "https://www.example.com"},
expectError: "the idp-url flag is only valid with auth as an argument and a auth-type flag of saml or oidc",
},
"repo argument with username-claim flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", usernameClaim: "user"},
expectError: "the username-claim flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"repo argument with client-id flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", clientID: "user"},
expectError: "the client-id flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"repo argument with client-secret flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", clientSecret: "user"},
expectError: "the client-secret flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"repo argument with cert-path flag fails": {
args: []string{"repo"},
flags: configOpts{url: "https://packagemanager.posit.co", source: "cran", certPath: "cert.crt"},
Expand All @@ -198,31 +97,6 @@ func TestConfigParamsValidate(t *testing.T) {
flags: configOpts{url: "https://colorado.posit.co/rsc", source: "cran"},
expectError: "the source flag is only valid for repo",
},
"connect-url argument with auth-type flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", authType: "saml"},
expectError: "the auth-type flag is only valid for auth",
},
"connect-url argument with idp-url flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", idpURL: "https://www.example.com"},
expectError: "the idp-url flag is only valid with auth as an argument and a auth-type flag of saml or oidc",
},
"connect-url argument with username-claim flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", usernameClaim: "user"},
expectError: "the username-claim flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"connect-url argument with client-id flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", clientID: "user"},
expectError: "the client-id flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"connect-url argument with client-secret flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", clientSecret: "user"},
expectError: "the client-secret flag is only valid with auth as an argument and a auth-type flag of oidc",
},
"connect-url argument with cert-path flag fails": {
args: []string{"connect-url"},
flags: configOpts{url: "https://packagemanager.posit.co", certPath: "cert.crt"},
Expand Down Expand Up @@ -261,34 +135,6 @@ func TestConfigParamsValidate(t *testing.T) {

// TODO TestConfigSSLCommandIntegration tests the config command with the ssl arg in a Docker container.

// TestConfigAuthSAMLCommandIntegration tests the config command with the auth arg, auth-type flag set to saml and idp-url flag set in a Docker container.
func TestConfigAuthSAMLCommandIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// TODO actually verify the contents of rserver.conf
t.Parallel()

installCommand := []string{"./wbi", "config", "auth", "--auth-type=saml", "--idp-url=https://www.example.com"}
successMessage := []string{"=== Writing to the file /etc/rstudio/rserver.conf:"}

IntegrationContainerRunner(t, "Dockerfile.Workbench", installCommand, successMessage, false)
}

// TestConfigAuthOIDCCommandIntegration tests the config command with the auth arg, auth-type flag set to oidc, idp-url flag, client-id flag and client-secret flag set in a Docker container.
func TestConfigAuthOIDCCommandIntegration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// TODO actually verify the contents of rserver.conf
t.Parallel()

installCommand := []string{"./wbi", "config", "auth", "--auth-type=oidc", "--idp-url=https://www.example.com", "--client-id=awdawdawd", "--client-secret=adwawdawdfgawa"}
successMessage := []string{"=== Writing to the file /etc/rstudio/rserver.conf:"}

IntegrationContainerRunner(t, "Dockerfile.Workbench", installCommand, successMessage, false)
}

// TestConfigRepoCRANCommandIntegration tests the config command with the repo arg, url flag set to Public Package Manager and source flag set to cran in a Docker container.
func TestConfigRepoCRANCommandIntegration(t *testing.T) {
if testing.Short() {
Expand Down
Loading

0 comments on commit a6190e4

Please sign in to comment.