move Azure Device Code plugin for sshpiperd out of tree (#453)

This commit is contained in:
Boshi Lian 2024-10-17 23:36:06 -07:00 committed by GitHub
parent 479d78e3a0
commit 57d0e21787
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 0 additions and 191 deletions

View file

@ -1,19 +0,0 @@
# Azure Device Code for sshpiperd
Support Azure AD device code grant, [More info](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code)
sshpier will ask user to login using webpage
```
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code ****** to authenticate.
```
NOTE: This is an additional challenge plugin. 🔒 you must use it with other routing plugins.
## Usage
Note: you may want to set `login-grace-time` to larger value (default: 30s) to avoid being kicked by `sshpiperd` if code was not entered in time.
```
sshpiperd --login-grace-time=2m azdevicecode --tenant-id 00000000-0000-0000-0000-000000000000 --client-id 00000000-0000-0000-0000-000000000000 -- other-plugin --other-option
```

View file

@ -1,101 +0,0 @@
//go:build full
package main
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
azidentity "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
a "github.com/microsoft/kiota-authentication-azure-go"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
log "github.com/sirupsen/logrus"
"github.com/tg123/sshpiper/libplugin"
"github.com/urfave/cli/v2"
)
func main() {
libplugin.CreateAndRunPluginTemplate(&libplugin.PluginTemplate{
Name: "azdevicecode",
Usage: "sshpiperd azure devicecode plugin, use devicecode to before ssh, see https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "tenant-id",
Usage: "Azure AD tenant id",
EnvVars: []string{"SSHPIPERD_AZDEVICECODE_TENANT_ID"},
Required: true,
},
&cli.StringFlag{
Name: "client-id",
Usage: "Azure AD client id",
EnvVars: []string{"SSHPIPERD_AZDEVICECODE_CLIENT_ID"},
Required: true,
},
&cli.BoolFlag{
Name: "no-read-graph",
Usage: "disable query user info from user graph",
EnvVars: []string{"SSHPIPERD_AZDEVICECODE_NOREADGRAPH"},
},
&cli.StringFlag{
Name: "scope",
Usage: "permission scope when querying user info",
EnvVars: []string{"SSHPIPERD_AZDEVICECODE_SCOPE"},
Value: "User.Read",
},
},
CreateConfig: func(c *cli.Context) (*libplugin.SshPiperPluginConfig, error) {
return &libplugin.SshPiperPluginConfig{
KeyboardInteractiveCallback: func(conn libplugin.ConnMetadata, client libplugin.KeyboardInteractiveChallenge) (*libplugin.Upstream, error) {
cred, err := azidentity.NewDeviceCodeCredential(&azidentity.DeviceCodeCredentialOptions{
TenantID: c.String("tenant-id"),
ClientID: c.String("client-id"),
UserPrompt: func(ctx context.Context, message azidentity.DeviceCodeMessage) error {
_, err := client("", message.Message, "", false)
return err
},
})
if err != nil {
return nil, err
}
if c.Bool("no-read-graph") {
_, err = cred.GetToken(context.Background(), policy.TokenRequestOptions{
Scopes: []string{c.String("scope")},
})
return nil, err
}
auth, err := a.NewAzureIdentityAuthenticationProviderWithScopes(cred, []string{c.String("scope")})
if err != nil {
return nil, err
}
adapter, err := msgraphsdk.NewGraphRequestAdapter(auth)
if err != nil {
return nil, err
}
gsclient := msgraphsdk.NewGraphServiceClient(adapter)
result, err := gsclient.Me().Get(context.Background(), nil)
if err != nil {
return nil, err
}
userId := *result.GetId()
log.Infof("success with challenged username: %s", userId)
return &libplugin.Upstream{
Auth: libplugin.CreateNextPluginAuth(map[string]string{
"UserId": *result.GetId(),
}),
}, nil
},
}, nil
},
})
}