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

refinements to ops verify-traffic to integrate and work with ziti edge login #2513

Merged
merged 5 commits into from
Oct 31, 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
2 changes: 1 addition & 1 deletion controller/oidc_auth/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ type HybridStorage struct {
serviceUsers cmap.ConcurrentMap[string, *Client]

startOnce sync.Once
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is unused, should we just remove it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dunno. it's an @andrewpmartinez question. I just made the linter happy :) i was pointed it out to andrew...

issuer string
//linter issue issuer string
config *Config

keys cmap.ConcurrentMap[string, *pubKey]
Expand Down
57 changes: 57 additions & 0 deletions internal/rest/mgmt/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@ package mgmt

import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"github.com/openziti/edge-api/rest_management_api_client"
rest_mgmt "github.com/openziti/edge-api/rest_management_api_client/current_api_session"
"github.com/openziti/edge-api/rest_management_api_client/identity"
"github.com/openziti/edge-api/rest_management_api_client/service"
"github.com/openziti/edge-api/rest_management_api_client/service_policy"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge-api/rest_util"
"github.com/openziti/ziti/ziti/util"
log "github.com/sirupsen/logrus"
"net/http"
"os"
"time"
)

Expand Down Expand Up @@ -80,4 +88,53 @@ func ServicePolicyFromFilter(client *rest_management_api_client.ZitiEdgeManageme

func NameFilter(name string) string {
return `name="` + name + `"`
}

func NewClient() (*rest_management_api_client.ZitiEdgeManagement, error) {
cachedCreds, _, loadErr := util.LoadRestClientConfig()
if loadErr != nil {
return nil, loadErr
}

cachedId := cachedCreds.EdgeIdentities[cachedCreds.Default] //only support default for now
if cachedId == nil {
return nil, errors.New("no identity found")
}

caPool := x509.NewCertPool()
if _, cacertErr := os.Stat(cachedId.CaCert); cacertErr == nil {
rootPemData, err := os.ReadFile(cachedId.CaCert)
if err != nil {
return nil, err
}
caPool.AppendCertsFromPEM(rootPemData)
} else {
return nil, errors.New("CA cert file not found in config file")
}

tlsConfig := &tls.Config{
RootCAs: caPool,
}

transport := &http.Transport{
TLSClientConfig: tlsConfig,
}

// Assign the transport to the default HTTP client
http.DefaultClient = &http.Client{
Transport: transport,
}
c, e := rest_util.NewEdgeManagementClientWithToken(http.DefaultClient, cachedId.Url, cachedId.Token)
if e != nil {
return nil, e
}

apiSessionParams := &rest_mgmt.GetCurrentAPISessionParams{
Context: context.Background(),
}
_, authErr := c.CurrentAPISession.GetCurrentAPISession(apiSessionParams, nil)
if authErr != nil {
return nil, errors.New("client not authenticated. login with 'ziti edge login' before executing")
}
return c, nil
}
4 changes: 2 additions & 2 deletions ziti/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ func NewCmdRoot(in io.Reader, out, err io.Writer, cmd *cobra.Command) *cobra.Com
opsCommands.AddCommand(database.NewCmdDb(out, err))
opsCommands.AddCommand(NewCmdLogFormat(out, err))
opsCommands.AddCommand(NewUnwrapIdentityFileCommand(out, err))
opsCommands.AddCommand(verify.NewVerifyNetwork())
opsCommands.AddCommand(verify.NewVerifyTraffic())
opsCommands.AddCommand(verify.NewVerifyNetwork(out, err))
opsCommands.AddCommand(verify.NewVerifyTraffic(out, err))

groups := templates.CommandGroups{
{
Expand Down
38 changes: 21 additions & 17 deletions ziti/cmd/edge/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ type LoginOptions struct {
FileCertCreds *edge_apis.IdentityCredentials
}

func AddLoginFlags(cmd *cobra.Command, options *LoginOptions) {
// allow interspersing positional args and flags
cmd.Flags().SetInterspersed(true)

cmd.Flags().StringVarP(&options.Username, "username", "u", "", "username to use for authenticating to the Ziti Edge Controller ")
cmd.Flags().StringVarP(&options.Password, "password", "p", "", "password to use for authenticating to the Ziti Edge Controller, if -u is supplied and -p is not, a value will be prompted for")
cmd.Flags().StringVarP(&options.Token, "token", "t", "", "if an api token has already been acquired, it can be set in the config with this option. This will set the session to read only by default")
cmd.Flags().StringVarP(&options.CaCert, "ca", "", "", "additional root certificates used by the Ziti Edge Controller")
cmd.Flags().BoolVar(&options.ReadOnly, "read-only", false, "marks this login as read-only. Note: this is not a guarantee that nothing can be changed on the server. Care should still be taken!")
cmd.Flags().BoolVarP(&options.Yes, "yes", "y", false, "If set, responds to prompts with yes. This will result in untrusted certs being accepted or updated.")
cmd.Flags().BoolVar(&options.IgnoreConfig, "ignore-config", false, "If set, does not use value from the config file for hostname or username. Values must be entered or will be prompted for.")
cmd.Flags().StringVarP(&options.ClientCert, "client-cert", "c", "", "A certificate used to authenticate")
cmd.Flags().StringVarP(&options.ClientKey, "client-key", "k", "", "The key to use with certificate authentication")
cmd.Flags().StringVarP(&options.ExtJwt, "ext-jwt", "e", "", "A file containing a JWT from an external provider to be used for authentication")
cmd.Flags().StringVarP(&options.File, "file", "f", "", "An identity file to use for authentication")

options.AddCommonFlags(cmd)
}

// NewLoginCmd creates the command
func NewLoginCmd(out io.Writer, errOut io.Writer) *cobra.Command {
options := &LoginOptions{
Expand All @@ -77,23 +96,8 @@ func NewLoginCmd(out io.Writer, errOut io.Writer) *cobra.Command {
},
SuggestFor: []string{},
}

// allow interspersing positional args and flags
cmd.Flags().SetInterspersed(true)

cmd.Flags().StringVarP(&options.Username, "username", "u", "", "username to use for authenticating to the Ziti Edge Controller ")
cmd.Flags().StringVarP(&options.Password, "password", "p", "", "password to use for authenticating to the Ziti Edge Controller, if -u is supplied and -p is not, a value will be prompted for")
cmd.Flags().StringVarP(&options.Token, "token", "t", "", "if an api token has already been acquired, it can be set in the config with this option. This will set the session to read only by default")
cmd.Flags().StringVarP(&options.CaCert, "ca", "", "", "additional root certificates used by the Ziti Edge Controller")
cmd.Flags().BoolVar(&options.ReadOnly, "read-only", false, "marks this login as read-only. Note: this is not a guarantee that nothing can be changed on the server. Care should still be taken!")
cmd.Flags().BoolVarP(&options.Yes, "yes", "y", false, "If set, responds to prompts with yes. This will result in untrusted certs being accepted or updated.")
cmd.Flags().BoolVar(&options.IgnoreConfig, "ignore-config", false, "If set, does not use value from the config file for hostname or username. Values must be entered or will be prompted for.")
cmd.Flags().StringVarP(&options.ClientCert, "client-cert", "c", "", "A certificate used to authenticate")
cmd.Flags().StringVarP(&options.ClientKey, "client-key", "k", "", "The key to use with certificate authentication")
cmd.Flags().StringVarP(&options.ExtJwt, "ext-jwt", "e", "", "A file containing a JWT from an external provider to be used for authentication")
cmd.Flags().StringVarP(&options.File, "file", "f", "", "An identity file to use for authentication")

options.AddCommonFlags(cmd)

AddLoginFlags(cmd, options)

return cmd
}
Expand Down
7 changes: 0 additions & 7 deletions ziti/cmd/verify/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ import (
"runtime"
)

type controller struct {
user string
pass string
host string
port string
}

func configureLogFormat(level logrus.Level) {
logrus.SetLevel(level)
logrus.SetFormatter(&logrus.TextFormatter{
Expand Down
3 changes: 2 additions & 1 deletion ziti/cmd/verify/ops_verify_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package verify

import (
"fmt"
"io"
"net"
"os"
"strings"
Expand Down Expand Up @@ -48,7 +49,7 @@ type stringMapList []interface{}

type StringMap map[string]interface{}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add this, just to ignore it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh - it was just a consistency thing... all the other commands pass these params so it was consistent. i had it with no params, but then verify-traffic needed in/out streams... so -- yeah that's 'why'

func NewVerifyNetwork() *cobra.Command {
func NewVerifyNetwork(_ io.Writer, _ io.Writer) *cobra.Command {
n := &network{}

cmd := &cobra.Command{
Expand Down
78 changes: 16 additions & 62 deletions ziti/cmd/verify/ops_verify_traffic.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ package verify
import (
"bufio"
"context"
"crypto/x509"
"fmt"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/foundation/v2/term"
"github.com/openziti/ziti/ziti/cmd/edge"
"github.com/sirupsen/logrus"
"io"
"net"
"os"
"strings"
"sync"
"time"
Expand All @@ -37,15 +36,14 @@ import (
"github.com/openziti/edge-api/rest_management_api_client/service_policy"
"github.com/openziti/edge-api/rest_management_api_client/terminator"
"github.com/openziti/edge-api/rest_model"
"github.com/openziti/edge-api/rest_util"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/sdk-golang/ziti/enroll"
"github.com/openziti/ziti/internal/rest/mgmt"
)


type traffic struct {
controller
loginOpts edge.LoginOptions
prefix string
mode string
cleanup bool
Expand All @@ -60,7 +58,7 @@ type traffic struct {
dialSPName string
}

func NewVerifyTraffic() *cobra.Command {
func NewVerifyTraffic(out io.Writer, errOut io.Writer) *cobra.Command {
t := &traffic{}
cmd := &cobra.Command{
Use: "verify-traffic",
Expand Down Expand Up @@ -97,9 +95,16 @@ func NewVerifyTraffic() *cobra.Command {
t.clientIdName = t.prefix + ".client"
t.bindSPName = t.prefix + ".bind"
t.dialSPName = t.prefix + ".dial"
client, err := t.newMgmtClient()
client, err := mgmt.NewClient()
if err != nil {
log.Fatal(err)
loginErr := t.loginOpts.Run()
if loginErr != nil {
log.Fatal(err)
}
client, err = mgmt.NewClient()
if err != nil {
log.Fatal(err)
}
}
t.client = client
if t.cleanup {
Expand All @@ -125,13 +130,11 @@ func NewVerifyTraffic() *cobra.Command {
cmd.Flags().StringVarP(&t.prefix, "prefix", "x", "", "[optional] The prefix to apply to generated objects, necessary when not using the 'both' role.")
cmd.Flags().StringVarP(&t.mode, "mode", "m", "", "[optional, default 'both'] The mode to perform: server, client, both.")
cmd.Flags().BoolVar(&t.cleanup, "cleanup", false, "Whether to perform cleanup.")
cmd.Flags().BoolVar(&t.verbose, "verbose", false, "Show additional output.")
cmd.Flags().BoolVar(&t.allowMultipleServers, "allow-multiple-servers", false, "Whether to allows the same server multiple times.")

cmd.Flags().StringVarP(&t.user, "username", "u", "", "username to use for authenticating to the Ziti Edge Controller ")
cmd.Flags().StringVarP(&t.pass, "password", "p", "", "password to use for authenticating to the Ziti Edge Controller, if -u is supplied and -p is not, a value will be prompted for")
cmd.Flags().StringVar(&t.host, "host", "", "the controller host")
cmd.Flags().StringVar(&t.port, "port", "", "the controller port")
edge.AddLoginFlags(cmd, &t.loginOpts)
t.loginOpts.Out = out
t.loginOpts.Err = errOut

return cmd
}
Expand Down Expand Up @@ -269,55 +272,6 @@ func waitForTerminator(client *rest_management_api_client.ZitiEdgeManagement, se
return false
}

func (t *traffic) newMgmtClient() (*rest_management_api_client.ZitiEdgeManagement, error) {
if t.user == "" {
t.user = os.Getenv("ZITI_USER")
if t.user == "" {
log.Info("user not supplied nor ZITI_USER set. defaulting to admin")
t.user = "admin"
}
}
if t.host == "" {
t.host = os.Getenv("ZITI_CTRL_EDGE_ADVERTISED_ADDRESS")
if t.host == "" {
log.Info("host not supplied nor ZITI_CTRL_EDGE_ADVERTISED_ADDRESS set. defaulting to localhost")
t.host = "localhost"
}
}
if t.port == "" {
t.port = os.Getenv("ZITI_CTRL_EDGE_ADVERTISED_PORT")
if t.port == "" {
log.Info("port not supplied nor ZITI_CTRL_EDGE_ADVERTISED_PORT set. defaulting to 1280")
t.port = "1280"
}
}

if t.pass == "" {
p := os.Getenv("ZITI_PWD")
t.pass = p
if t.pass == "" {
pass, err := term.PromptPassword("Enter password: ", false)
if err != nil {
log.Fatal(err)
}
t.pass = pass
}
}

ctrlAddress := "https://" + t.host + ":" + t.port

log.Infof("connecting with user %s to %s", t.user, ctrlAddress)
caCerts, err := rest_util.GetControllerWellKnownCas(ctrlAddress)
if err != nil {
log.Fatal(err)
}
caPool := x509.NewCertPool()
for _, ca := range caCerts {
caPool.AddCert(ca)
}
return rest_util.NewEdgeManagementClientWithUpdb(t.user, t.pass, ctrlAddress, caPool)
}

func createIdentity(client *rest_management_api_client.ZitiEdgeManagement, name string, roleAttributes rest_model.Attributes) *identity.CreateIdentityCreated {
falseVar := false
usrType := rest_model.IdentityTypeUser
Expand Down
Loading