예제 #1
0
func (h *PolicyHandler) AddResourceToPolicy(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/policies")
	h.M.Client = h.Config.OAuth2Client(cmd)

	if len(args) < 2 {
		fmt.Print(cmd.UsageString())
		return
	}

	policy, err := h.M.Get(args[0])
	pkg.Must(err, "Could not get policy: %s", err)

	err = h.M.Delete(args[0])
	if h.M.Dry {
		fmt.Printf("%s\n", err)
	} else {
		pkg.Must(err, "Could not prepare policy for update: %s", err)
	}

	p := policy.(*ladon.DefaultPolicy)
	p.Resources = append(p.Resources, args[1:]...)

	err = h.M.Create(policy)
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not update policy: %s", err)
	fmt.Printf("Added resources to policy %s", p.ID)
}
예제 #2
0
파일: host.go 프로젝트: jemacom/hydra
func runHostCmd(cmd *cobra.Command, args []string) {
	router := httprouter.New()
	serverHandler := &server.Handler{}
	serverHandler.Start(c, router)

	if ok, _ := cmd.Flags().GetBool("dangerous-auto-logon"); ok {
		logrus.Warnln("Do not use flag --dangerous-auto-logon in production.")
		err := c.Persist()
		pkg.Must(err, "Could not write configuration file: %s", err)
	}

	http.Handle("/", router)

	var srv = http.Server{
		Addr: c.GetAddress(),
		TLSConfig: &tls.Config{
			Certificates: []tls.Certificate{
				getOrCreateTLSCertificate(cmd),
			},
		},
	}

	var err error
	logrus.Infof("Starting server on %s", c.GetAddress())
	if ok, _ := cmd.Flags().GetBool("force-dangerous-http"); ok {
		logrus.Warnln("HTTPS disabled. Never do this in production.")
		err = srv.ListenAndServe()
	} else {
		err = srv.ListenAndServeTLS("", "")
	}
	pkg.Must(err, "Could not start server: %s %s.", err)
}
예제 #3
0
func (h *PolicyHandler) CreatePolicy(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/policies")
	h.M.Client = h.Config.OAuth2Client(cmd)

	files, _ := cmd.Flags().GetStringSlice("files")
	if len(files) > 0 {
		for _, path := range files {
			reader, err := os.Open(path)
			pkg.Must(err, "Could not open file %s: %s", path, err)
			var policy ladon.DefaultPolicy
			err = json.NewDecoder(reader).Decode(&policy)
			pkg.Must(err, "Could not parse JSON: %s", err)
			err = h.M.Create(&policy)
			pkg.Must(err, "Could not create policy: %s", err)
			fmt.Printf("Imported policy %s from %s.\n", policy.ID, path)
		}
		return
	}

	id, _ := cmd.Flags().GetString("id")
	description, _ := cmd.Flags().GetString("description")
	subjects, _ := cmd.Flags().GetStringSlice("subjects")
	resources, _ := cmd.Flags().GetStringSlice("resources")
	actions, _ := cmd.Flags().GetStringSlice("actions")
	isAllow, _ := cmd.Flags().GetBool("allow")
	if len(subjects) == 0 || len(resources) == 0 || len(actions) == 0 {
		fmt.Println(cmd.UsageString())
		fmt.Println("")
		fmt.Println("Got empty subject, resource or action list")
	}

	effect := ladon.DenyAccess
	if isAllow {
		effect = ladon.AllowAccess
	}

	policy := &ladon.DefaultPolicy{
		ID:          id,
		Description: description,
		Subjects:    subjects,
		Resources:   resources,
		Actions:     actions,
		Effect:      effect,
	}
	err := h.M.Create(policy)
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not create policy: %s", err)
	fmt.Printf("Created policy %s.\n", policy.ID)

}
예제 #4
0
파일: handler.go 프로젝트: jemacom/hydra
func (h *Handler) createRS256KeysIfNotExist(c *config.Config, set, lookup string) {
	ctx := c.Context()
	generator := jwk.RS256Generator{}

	if _, err := ctx.KeyManager.GetKey(set, lookup); errors.Is(err, pkg.ErrNotFound) {
		logrus.Warnf("Key pair for signing %s is missing. Creating new one.", set)

		keys, err := generator.Generate("")
		pkg.Must(err, "Could not generate %s key: %s", set, err)

		err = ctx.KeyManager.AddKeySet(set, keys)
		pkg.Must(err, "Could not persist %s key: %s", set, err)
	}
}
예제 #5
0
func init() {
	keys, err := keyGenerator.Generate("")
	pkg.Must(err, "")
	keyManager.AddKeySet(ConsentChallengeKey, keys)

	keys, err = keyGenerator.Generate("")
	pkg.Must(err, "")
	keyManager.AddKeySet(ConsentEndpointKey, keys)
	ts = httptest.NewServer(router)

	handler.SetRoutes(router)
	store.Clients["app"] = &fosite.DefaultClient{
		ID:            "app",
		Secret:        []byte("secret"),
		RedirectURIs:  []string{ts.URL + "/callback"},
		ResponseTypes: []string{"id_token", "code", "token"},
		GrantTypes:    []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"},
	}

	c, _ := url.Parse(ts.URL + "/consent")
	handler.ConsentURL = *c

	h, _ := hasher.Hash([]byte("secret"))
	store.Clients["app-client"] = &fosite.DefaultClient{
		ID:            "app-client",
		Secret:        h,
		RedirectURIs:  []string{ts.URL + "/callback"},
		ResponseTypes: []string{"id_token", "code", "token"},
		GrantTypes:    []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"},
	}

	oauthConfig = &oauth2.Config{
		ClientID:     "app-client",
		ClientSecret: "secret",
		Endpoint: oauth2.Endpoint{
			AuthURL:  ts.URL + "/oauth2/auth",
			TokenURL: ts.URL + "/oauth2/token",
		},
		RedirectURL: ts.URL + "/callback",
		Scopes:      []string{"hydra"},
	}

	oauthClientConfig = &clientcredentials.Config{
		ClientID:     "app-client",
		ClientSecret: "secret",
		TokenURL:     ts.URL + "/oauth2/token",
		Scopes:       []string{"hydra"},
	}
}
예제 #6
0
파일: handler.go 프로젝트: jemacom/hydra
func (h *Handler) createRootIfNewInstall(c *config.Config) {
	ctx := c.Context()

	clients, err := h.Clients.Manager.GetClients()
	pkg.Must(err, "Could not fetch client list: %s", err)
	if len(clients) != 0 {
		return
	}

	rs, err := pkg.GenerateSecret(16)
	pkg.Must(err, "Could notgenerate secret because %s", err)
	secret := []byte(string(rs))

	logrus.Warn("No clients were found. Creating a temporary root client...")
	root := &fosite.DefaultClient{
		Name:          "This temporary client is generated by hydra and is granted all of hydra's administrative privileges. It must be removed when everything is set up.",
		GrantTypes:    []string{"client_credentials", "authorization_code"},
		ResponseTypes: []string{"token", "code"},
		GrantedScopes: []string{"hydra", "core"},
		RedirectURIs:  []string{"http://localhost:4445/callback"},
		Secret:        secret,
	}

	err = h.Clients.Manager.CreateClient(root)
	pkg.Must(err, "Could not create temporary root because %s", err)
	err = ctx.LadonManager.Create(&ladon.DefaultPolicy{
		Description: "This is a policy created by hydra and issued to the first client. It grants all of hydra's administrative privileges to the client and enables the client_credentials response type.",
		Subjects:    []string{root.GetID()},
		Effect:      ladon.AllowAccess,
		Resources:   []string{"rn:hydra:<.*>"},
		Actions:     []string{"<.*>"},
	})
	pkg.Must(err, "Could not create admin policy because %s", err)

	c.Lock()
	c.ClientID = root.ID
	c.ClientSecret = string(secret)
	c.Unlock()

	logrus.Warn("Temporary root client created.")
	logrus.Warnf("client_id: %s", root.GetID())
	logrus.Warnf("client_secret: %s", string(secret))
	logrus.Warn("The root client must be removed in production. The root's credentials could be accidentally logged.")
}
예제 #7
0
func (h *JWKHandler) GetKeys(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/keys")
	h.M.Client = h.Config.OAuth2Client(cmd)
	if len(args) == 0 {
		fmt.Println(cmd.UsageString())
		return
	}

	keys, err := h.M.GetKeySet(args[0])
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not generate keys: %s", err)

	out, err := json.MarshalIndent(keys, "", "\t")
	pkg.Must(err, "Could not marshall keys: %s", err)

	fmt.Printf("%s\n", out)
}
예제 #8
0
func (h *PolicyHandler) GetPolicy(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/policies")
	h.M.Client = h.Config.OAuth2Client(cmd)

	if len(args) == 0 {
		fmt.Print(cmd.UsageString())
		return
	}

	policy, err := h.M.Get(args[0])
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not delete policy: %s", err)

	out, err := json.MarshalIndent(policy, "", "\t")
	pkg.Must(err, "Could not retrieve policy: %s", err)

	fmt.Printf("%s\n", out)
}
예제 #9
0
func (h *ClientHandler) ImportClients(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	if len(args) == 0 {
		fmt.Print(cmd.UsageString())
		return
	}

	for _, path := range args {
		reader, err := os.Open(path)
		pkg.Must(err, "Could not open file %s: %s", path, err)
		var client fosite.DefaultClient
		err = json.NewDecoder(reader).Decode(&client)
		pkg.Must(err, "Could not parse JSON: %s", err)

		err = h.M.CreateClient(&client)
		if h.M.Dry {
			fmt.Printf("%s\n", err)
			continue
		}
		pkg.Must(err, "Could not create client: %s", err)
		fmt.Printf("Imported client %s from %s.\n", client.ID, path)
	}
}
예제 #10
0
func (h *ClientHandler) CreateClient(cmd *cobra.Command, args []string) {
	var err error

	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/clients")
	h.M.Client = h.Config.OAuth2Client(cmd)

	responseTypes, _ := cmd.Flags().GetStringSlice("response-types")
	grantTypes, _ := cmd.Flags().GetStringSlice("grant-types")
	allowedScopes, _ := cmd.Flags().GetStringSlice("allowed-scopes")
	callbacks, _ := cmd.Flags().GetStringSlice("callbacks")
	name, _ := cmd.Flags().GetString("name")
	id, _ := cmd.Flags().GetString("id")

	secret, err := pkg.GenerateSecret(26)
	pkg.Must(err, "Could not generate secret: %s", err)

	client := &fosite.DefaultClient{
		ID:            id,
		Secret:        secret,
		ResponseTypes: responseTypes,
		GrantedScopes: allowedScopes,
		GrantTypes:    grantTypes,
		RedirectURIs:  callbacks,
		Name:          name,
	}
	err = h.M.CreateClient(client)
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not create client: %s", err)

	fmt.Printf("Client ID: %s\n", client.ID)
	fmt.Printf("Client Secret: %s\n", secret)
}
예제 #11
0
func (h *JWKHandler) DeleteKeys(cmd *cobra.Command, args []string) {
	h.M.Endpoint = h.Config.Resolve("/keys")
	h.M.Client = h.Config.OAuth2Client(cmd)
	if len(args) == 0 {
		fmt.Println(cmd.UsageString())
		return
	}

	err := h.M.DeleteKeySet(args[0])
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not generate keys: %s", err)
	fmt.Println("Key set deleted.")
}
예제 #12
0
파일: config.go 프로젝트: jemacom/hydra
func (c *Config) Resolve(join ...string) *url.URL {
	c.Lock()
	defer c.Unlock()

	if c.cluster == nil {
		cluster, err := url.Parse(c.ClusterURL)
		c.cluster = cluster
		pkg.Must(err, "Could not parse cluster url: %s", err)
	}

	if len(join) == 0 {
		return c.cluster
	}

	return pkg.JoinURL(c.cluster, join...)
}
예제 #13
0
func (h *ConnectionHandler) DeleteConnection(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Client = h.Config.OAuth2Client(cmd)
	h.M.Endpoint = h.Config.Resolve("/connections")
	if len(args) == 0 {
		fmt.Print(cmd.UsageString())
		return
	}

	for _, arg := range args {
		err := h.M.Delete(arg)
		if h.M.Dry {
			fmt.Printf("%s\n", err)
			continue
		}
		pkg.Must(err, "Could not delete connection: %s", err)
		fmt.Printf("Connection %s deleted.\n", arg)
	}
}
예제 #14
0
파일: host.go 프로젝트: jemacom/hydra
func getOrCreateTLSCertificate(cmd *cobra.Command) tls.Certificate {
	if cert := loadCertificateFromFile(cmd); cert != nil {
		return *cert
	} else if cert := loadCertificateFromEnv(cmd); cert != nil {
		return *cert
	}

	ctx := c.Context()
	keys, err := ctx.KeyManager.GetKey(TLSKeyName, "private")
	if errors.Is(err, pkg.ErrNotFound) {
		logrus.Warn("Key for TLS not found. Creating new one.")

		keys, err = new(jwk.ECDSA256Generator).Generate("")
		pkg.Must(err, "Could not generate key: %s", err)

		cert, err := createSelfSignedCertificate(jwk.First(keys.Key("private")).Key)
		pkg.Must(err, "Could not create X509 PEM Key Pair: %s", err)

		private := jwk.First(keys.Key("private"))
		private.Certificates = []*x509.Certificate{cert}
		keys = &jose.JsonWebKeySet{
			Keys: []jose.JsonWebKey{
				*private,
				*jwk.First(keys.Key("public")),
			},
		}

		err = ctx.KeyManager.AddKeySet(TLSKeyName, keys)
		pkg.Must(err, "Could not persist key: %s", err)
	} else {
		pkg.Must(err, "Could not retrieve key: %s", err)
	}

	private := jwk.First(keys.Key("private"))
	block, err := jwk.PEMBlockForKey(private.Key)
	if err != nil {
		pkg.Must(err, "Could not encode key to PEM: %s", err)
	}

	if len(private.Certificates) == 0 {
		logrus.Fatal("TLS certificate chain can not be empty")
	}

	pemCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: private.Certificates[0].Raw})
	pemKey := pem.EncodeToMemory(block)
	cert, err := tls.X509KeyPair(pemCert, pemKey)
	pkg.Must(err, "Could not decode certificate: %s", err)

	return cert
}
예제 #15
0
func (h *ClientHandler) DeleteClient(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Endpoint = h.Config.Resolve("/clients")
	h.M.Client = h.Config.OAuth2Client(cmd)
	if len(args) == 0 {
		fmt.Print(cmd.UsageString())
		return
	}

	for _, c := range args {
		err := h.M.DeleteClient(c)
		if h.M.Dry {
			fmt.Printf("%s\n", err)
			continue
		}
		pkg.Must(err, "Could not delete client: %s", err)
	}

	fmt.Println("Client(s) deleted.")
}
예제 #16
0
파일: config.go 프로젝트: jemacom/hydra
func (c *Config) GetSystemSecret() []byte {
	c.Lock()
	defer c.Unlock()

	if len(c.SystemSecret) >= 16 {
		hash := sha256.Sum256(c.SystemSecret)
		c.SystemSecret = hash[:]
		return c.SystemSecret
	}

	logrus.Warnf("Expected system secret to be at least %d characters long but only got %d characters.", 32, len(c.SystemSecret))
	logrus.Warnln("Generating a random system secret...")
	var err error
	c.SystemSecret, err = pkg.GenerateSecret(32)
	pkg.Must(err, "Could not generate global secret: %s", err)
	logrus.Warnf("Generated system secret: %s", c.SystemSecret)
	logrus.Warnln("Do not auto-generate system secrets in production.")
	hash := sha256.Sum256(c.SystemSecret)
	c.SystemSecret = hash[:]
	return c.SystemSecret
}
예제 #17
0
func (h *ConnectionHandler) CreateConnection(cmd *cobra.Command, args []string) {
	h.M.Dry = *h.Config.Dry
	h.M.Client = h.Config.OAuth2Client(cmd)
	h.M.Endpoint = h.Config.Resolve("/connections")
	if len(args) != 3 {
		fmt.Print(cmd.UsageString())
		return
	}

	err := h.M.Create(&connection.Connection{
		ID:            uuid.New(),
		Provider:      args[0],
		LocalSubject:  args[1],
		RemoteSubject: args[2],
	})
	if h.M.Dry {
		fmt.Printf("%s\n", err)
		return
	}
	pkg.Must(err, "Could not create connection: %s", err)
}
예제 #18
0
파일: token_self.go 프로젝트: jemacom/hydra
	Short: "Generate an OAuth2 token the client grant type",
	Long:  "This command uses the CLI's credentials to create an access token.",
	Run: func(cmd *cobra.Command, args []string) {
		ctx := context.Background()
		if ok, _ := cmd.Flags().GetBool("skip-tls-verify"); ok {
			fmt.Println("Warning: Skipping TLS Certificate Verification.")
			ctx = context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
			}})
		}

		oauthConfig := clientcredentials.Config{
			ClientID:     c.ClientID,
			ClientSecret: c.ClientSecret,
			TokenURL:     pkg.JoinURLStrings(c.ClusterURL, "/oauth2/token"),
			Scopes: []string{
				"core",
				"hydra",
			},
		}

		t, err := oauthConfig.Token(ctx)
		pkg.Must(err, "Could not authenticate, because: %s\n", err)
		fmt.Printf("%s", t.AccessToken)
	},
}

func init() {
	tokenCmd.AddCommand(tokenSelfCmd)
}
예제 #19
0
파일: token_user.go 프로젝트: jemacom/hydra
				TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
			}})
		}

		conf := oauth2.Config{
			ClientID:     c.ClientID,
			ClientSecret: c.ClientSecret,
			Endpoint: oauth2.Endpoint{
				TokenURL: pkg.JoinURLStrings(c.ClusterURL, "/oauth2/token"),
				AuthURL:  pkg.JoinURLStrings(c.ClusterURL, "/oauth2/auth"),
			},
			Scopes: []string{"core", "hydra"},
		}

		state, err := sequence.RuneSequence(24, []rune("abcdefghijklmnopqrstuvwxyz"))
		pkg.Must(err, "Could not generate random state: %s", err)

		nonce, err := sequence.RuneSequence(24, []rune("abcdefghijklmnopqrstuvwxyz"))
		pkg.Must(err, "Could not generate random state: %s", err)

		location := conf.AuthCodeURL(string(state)) + "&nonce=" + string(nonce)

		if ok, _ := cmd.Flags().GetBool("no-open"); !ok {
			webbrowser.Open(location)
		}
		fmt.Printf("If your browser does not open automatically, navigate to: %s\n", location)

		fmt.Println("Setting up callback listener on http://localhost:4445/callback")
		fmt.Println("Press ctrl + c on Linux / Windows or cmd + c on OSX to end the process.")

		srv := &graceful.Server{