Skip to content

Commit

Permalink
Add the dcos auth list-providers command (dcos#1187)
Browse files Browse the repository at this point in the history
This adds the `dcos auth list-providers`. It lists available login providers from the current config's `/acs/api/v1/auth/providers` endpoint or the cluster's URL, if any is passed as argument.

It is capable of showing providers as a table list or as JSON.
  • Loading branch information
br-lewis authored and bamarni committed Mar 29, 2018
1 parent 207d71f commit fe1fd6f
Show file tree
Hide file tree
Showing 21 changed files with 3,068 additions and 2 deletions.
14 changes: 13 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@
[[constraint]]
name = "github.com/spf13/afero"
version = "1.0.2"

[[constraint]]
branch = "master"
name = "github.com/olekukonko/tablewriter"
22 changes: 21 additions & 1 deletion pkg/cmd/dcos.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd

import (
"fmt"
"io"
"os"
"os/user"
"path/filepath"
Expand Down Expand Up @@ -46,8 +47,27 @@ func attachedCluster() *Cluster {
os.Exit(1)
}

// Default to the old config path. If .dcos/clusters exists, it will search that for an attached cluster and if it
// finds one there, it will override this var to use that cluster's config instead.
configPath := filepath.Join(usr.HomeDir, ".dcos")

clustersDir := filepath.Join(configPath, "clusters")

// Find the config of the attached cluster.
err = filepath.Walk(clustersDir, func(path string, info os.FileInfo, err error) error {
if filepath.Base(path) == "attached" {
configPath = filepath.Dir(path)
return io.EOF
}
return nil
})
if err != io.EOF && err != filepath.SkipDir && err != nil {
fmt.Println(err)
}


// Make sure "~/.dcos/dcos.toml" exists.
path := filepath.Join(dir, "dcos.toml")
path := filepath.Join(configPath, "dcos.toml")
f, err := os.OpenFile(path, os.O_RDONLY|os.O_CREATE, 0600)
if err != nil {
fmt.Printf("Couldn't create config file \"%s\": %s.\n", path, err)
Expand Down
123 changes: 123 additions & 0 deletions pkg/cmd/dcos_auth_listproviders.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package cmd

import (
"encoding/json"
"fmt"
"os"

"github.com/dcos/dcos-cli/pkg/httpclient"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
)

// These are the different auth types that DC/OS supports with the names that they'll be given from the providers
// endpoint.
const (
LoginTypeDCOSUidPassword = "dcos-uid-password"
LoginTypeDCOSUidServiceKey = "dcos-uid-servicekey"
LoginTypeDCOSUidPasswordLDAP = "dcos-uid-password-ldap"
LoginTypeSAMLSpInitiated = "saml-sp-initiated"
LoginTypeOIDCAuthCodeFlow = "oidc-authorization-code-flow"
LoginTypeOIDCImplicitFlow = "oidc-implicit-flow"
)

var jsonOutput bool

// authListProvidersCmd represents the `dcos auth list-providers` subcommand.
var authListProvidersCmd = &cobra.Command{
Use: "list-providers",
Args: cobra.MaximumNArgs(1),
RunE: listProviders,
}

func init() {
authCmd.AddCommand(authListProvidersCmd)
authListProvidersCmd.Flags().BoolVar(&jsonOutput, "json", false, "returns providers in json format")
}

func listProviders(cmd *cobra.Command, args []string) error {
var url string
if len(args) == 0 {
conf := attachedCluster().Config
url = conf.URL()
} else {
url = args[0]
}

providers, err := getProviders(url)
if err != nil {
return err
}

if jsonOutput {
// Re-marshal it into json with indents added in for pretty printing.
out, err := json.MarshalIndent(providers, "", "\t")
if err != nil {
return err
}
fmt.Println(string(out))
} else {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"PROVIDER ID", "AUTHENTICATION TYPE"})
// Turn off wrapping because it seems to wrap even if the column is set to be wide enough.
table.SetAutoWrapText(false)
table.SetBorder(false)
table.SetRowSeparator(" ")
table.SetColumnSeparator(" ")
table.SetCenterSeparator(" ")

for name, provider := range *providers {
desc, err := loginTypeDescription(provider.AuthenticationType, provider)
if err != nil {
return err
}
table.Append([]string{name, desc})
}
table.Render()
}

return nil
}

func getProviders(baseURL string) (*map[string]loginProvider, error) {
client := httpclient.New(baseURL)
response, err := client.Get("/acs/api/v1/auth/providers")
if err != nil {
return nil, err
}
defer response.Body.Close()

var resp map[string]loginProvider
err = json.NewDecoder(response.Body).Decode(&resp)
return &resp, err
}

func loginTypeDescription(loginType string, provider loginProvider) (string, error) {
switch loginType {
case LoginTypeDCOSUidPassword:
return "Log in using a standard DC/OS user account (username and password)", nil
case LoginTypeDCOSUidServiceKey:
return "Log in using a DC/OS service user account (username and private key)", nil
case LoginTypeDCOSUidPasswordLDAP:
return "Log in in using an LDAP user account (username and password)", nil
case LoginTypeSAMLSpInitiated:
return fmt.Sprintf("Log in using SAML 2.0 (%s)", provider.Description), nil
case LoginTypeOIDCImplicitFlow:
return fmt.Sprintf("Log in using OpenID Connect(%s)", provider.Description), nil
case LoginTypeOIDCAuthCodeFlow:
return fmt.Sprintf("Log in using OpenID Connect(%s)", provider.Description), nil
default:
return "", fmt.Errorf("unknown login provider %s", loginType)
}
}

type loginProvider struct {
AuthenticationType string `json:"authentication-type"`
ClientMethod string `json:"client-method"`
Config loginListProviderConfig `json:"config"`
Description string `json:"description"`
}

type loginListProviderConfig struct {
StartFlowURL string `json:"start_flow_url"`
}
8 changes: 8 additions & 0 deletions vendor/github.com/mattn/go-runewidth/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions vendor/github.com/mattn/go-runewidth/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions vendor/github.com/mattn/go-runewidth/README.mkd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fe1fd6f

Please sign in to comment.