diff --git a/api/proto/teleport/legacy/types/types.proto b/api/proto/teleport/legacy/types/types.proto
index 3e2dd18000b27..eec214cdce44d 100644
--- a/api/proto/teleport/legacy/types/types.proto
+++ b/api/proto/teleport/legacy/types/types.proto
@@ -6010,6 +6010,9 @@ message PluginEntraIDSyncSettings {
// DefaultOwners are the default owners for all imported access lists.
repeated string default_owners = 1;
+
+ // SSOConnectorID is the name of the Teleport SSO connector created and used by the Entra ID plugin
+ string sso_connector_id = 2;
}
// AccessGraphSettings controls settings for syncing access graph specific data.
diff --git a/api/types/plugin.go b/api/types/plugin.go
index ca75f87daba08..40885ab180b71 100644
--- a/api/types/plugin.go
+++ b/api/types/plugin.go
@@ -634,6 +634,9 @@ func (c *PluginEntraIDSettings) Validate() error {
if len(c.SyncSettings.DefaultOwners) == 0 {
return trace.BadParameter("sync_settings.default_owners must be set")
}
+ if c.SyncSettings.SsoConnectorId == "" {
+ return trace.BadParameter("sync_settings.sso_connector_id must be set")
+ }
return nil
}
diff --git a/api/types/plugin_test.go b/api/types/plugin_test.go
index cf35b3b41bd18..21ad433df19e2 100644
--- a/api/types/plugin_test.go
+++ b/api/types/plugin_test.go
@@ -855,7 +855,8 @@ func TestPluginEntraIDValidation(t *testing.T) {
return &PluginSpecV1_EntraId{
EntraId: &PluginEntraIDSettings{
SyncSettings: &PluginEntraIDSyncSettings{
- DefaultOwners: []string{"admin"},
+ DefaultOwners: []string{"admin"},
+ SsoConnectorId: "myconnector",
},
},
}
@@ -891,6 +892,13 @@ func TestPluginEntraIDValidation(t *testing.T) {
},
assertErr: requireNamedBadParameterError("sync_settings.default_owners"),
},
+ {
+ name: "missing sso connector name",
+ mutateSettings: func(s *PluginSpecV1_EntraId) {
+ s.EntraId.SyncSettings.SsoConnectorId = ""
+ },
+ assertErr: requireNamedBadParameterError("sync_settings.sso_connector_id"),
+ },
}
for _, tc := range testCases {
diff --git a/api/types/types.pb.go b/api/types/types.pb.go
index 8b082e771de48..b9c3167ccc875 100644
--- a/api/types/types.pb.go
+++ b/api/types/types.pb.go
@@ -15528,7 +15528,9 @@ var xxx_messageInfo_PluginEntraIDSettings proto.InternalMessageInfo
// Defines settings for syncing users and access lists from Entra ID.
type PluginEntraIDSyncSettings struct {
// DefaultOwners are the default owners for all imported access lists.
- DefaultOwners []string `protobuf:"bytes,1,rep,name=default_owners,json=defaultOwners,proto3" json:"default_owners,omitempty"`
+ DefaultOwners []string `protobuf:"bytes,1,rep,name=default_owners,json=defaultOwners,proto3" json:"default_owners,omitempty"`
+ // SSOConnectorID is the name of the Teleport SSO connector created and used by the Entra ID plugin
+ SsoConnectorId string `protobuf:"bytes,2,opt,name=sso_connector_id,json=ssoConnectorId,proto3" json:"sso_connector_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -19050,7 +19052,7 @@ func init() {
func init() { proto.RegisterFile("teleport/legacy/types/types.proto", fileDescriptor_9198ee693835762e) }
var fileDescriptor_9198ee693835762e = []byte{
- // 25964 bytes of a gzipped FileDescriptorProto
+ // 25970 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x70, 0x1c, 0x49,
0x7a, 0x20, 0x36, 0xfd, 0x00, 0xd0, 0xf8, 0xf0, 0x6a, 0x24, 0x40, 0x12, 0xc4, 0x90, 0xd3, 0x9c,
0xe2, 0x0c, 0x87, 0x9c, 0x07, 0xb9, 0x04, 0x77, 0xb8, 0x3b, 0x3b, 0xaf, 0x6d, 0x74, 0x83, 0x44,
@@ -20415,265 +20417,266 @@ var fileDescriptor_9198ee693835762e = []byte{
0x09, 0xf7, 0xdb, 0xd7, 0xf5, 0xc4, 0x61, 0xf2, 0x55, 0x21, 0xd2, 0x69, 0xe5, 0xde, 0x2b, 0xba,
0xf7, 0x5b, 0x41, 0xf7, 0x22, 0x07, 0x37, 0x59, 0x89, 0x2e, 0xcb, 0x24, 0xd9, 0x53, 0x12, 0xf5,
0x5d, 0x99, 0xe4, 0x43, 0x38, 0x25, 0x96, 0xca, 0x9e, 0x6b, 0x75, 0xf7, 0x43, 0x76, 0xbc, 0xa1,
- 0xaf, 0x24, 0xb1, 0xe3, 0x6b, 0xe8, 0x36, 0xc3, 0x0f, 0xb8, 0xce, 0x59, 0x71, 0xa0, 0xe8, 0xc3,
- 0xaa, 0x3c, 0xf4, 0x13, 0x5a, 0x93, 0xb0, 0x06, 0x53, 0x09, 0x6b, 0x50, 0x70, 0xfa, 0xa1, 0x14,
- 0x5c, 0x38, 0xae, 0x25, 0x64, 0x1b, 0x4e, 0xe3, 0x6b, 0xb6, 0xe7, 0x04, 0x9d, 0xa9, 0x37, 0xac,
- 0xc6, 0x3e, 0x15, 0x73, 0x6f, 0x24, 0x76, 0xa9, 0xdb, 0xad, 0xd5, 0x36, 0x94, 0xde, 0x74, 0xbb,
- 0x35, 0xcf, 0x91, 0xbf, 0x4b, 0x8c, 0x5c, 0xb4, 0xa1, 0x09, 0xcf, 0x0f, 0xa0, 0x54, 0x3e, 0x96,
- 0x94, 0xfa, 0xb1, 0x5c, 0x86, 0xfc, 0x2e, 0x6d, 0x32, 0xc1, 0x88, 0x36, 0xb1, 0x69, 0x0f, 0x96,
- 0x78, 0x4e, 0x3d, 0x73, 0x3a, 0x80, 0xd7, 0x3c, 0xe7, 0xfe, 0x92, 0xa8, 0xa5, 0x2d, 0xf7, 0x3d,
- 0x55, 0xf0, 0x22, 0x57, 0x61, 0x2e, 0xe2, 0x81, 0x1f, 0xba, 0x74, 0x9a, 0xb3, 0xac, 0x48, 0x8f,
- 0xd7, 0xf2, 0x22, 0x4c, 0xca, 0xc1, 0x75, 0x03, 0xc7, 0x10, 0x73, 0x42, 0xc0, 0xd8, 0xda, 0x15,
- 0xd5, 0xfd, 0xdd, 0xb4, 0x14, 0x84, 0x96, 0x1d, 0xc7, 0xf7, 0x7c, 0xd7, 0xea, 0x6a, 0xb7, 0x21,
- 0xd2, 0x86, 0xb3, 0x8e, 0xd5, 0xf3, 0xf7, 0x97, 0xea, 0xec, 0x5f, 0xc7, 0x95, 0x5e, 0x9a, 0x0d,
- 0x69, 0xdf, 0x36, 0xb1, 0x74, 0x4d, 0xdf, 0x10, 0x8b, 0x0c, 0xbb, 0xa8, 0x22, 0xb3, 0x73, 0x5b,
- 0xe1, 0xba, 0xfa, 0x9c, 0x79, 0x86, 0xf3, 0x8c, 0x61, 0x91, 0x55, 0xd0, 0xf2, 0xd5, 0x27, 0x5e,
- 0x87, 0x94, 0xdc, 0xf2, 0x3a, 0xd7, 0x89, 0x1d, 0x25, 0xb9, 0xfd, 0x7b, 0x30, 0x6e, 0x37, 0x45,
- 0x54, 0x38, 0x71, 0x29, 0xd2, 0x05, 0xf1, 0x4a, 0x93, 0x07, 0x89, 0x0b, 0x79, 0xb0, 0x1b, 0x95,
- 0x2d, 0xa0, 0xcb, 0x53, 0xda, 0xbd, 0xd1, 0x58, 0x96, 0x67, 0x6e, 0x9c, 0x2c, 0x96, 0x7a, 0xfc,
- 0x34, 0x8c, 0x7a, 0x4a, 0x98, 0x3a, 0x53, 0xfc, 0x32, 0xfe, 0x02, 0x5c, 0x1e, 0x76, 0x8c, 0xc8,
- 0x1b, 0x40, 0xfa, 0x0c, 0xf8, 0xb8, 0x39, 0x6b, 0xc5, 0xc6, 0xed, 0x45, 0x50, 0xe3, 0x6c, 0xd9,
- 0x72, 0xc2, 0x25, 0x6c, 0xcb, 0xb5, 0x8d, 0x77, 0x61, 0x5a, 0xbf, 0x28, 0x93, 0xd7, 0x20, 0x1b,
- 0x70, 0x9d, 0x0e, 0x14, 0xba, 0x2a, 0x12, 0xe3, 0x6d, 0x22, 0x92, 0xf1, 0x4f, 0xd3, 0x30, 0x97,
- 0x70, 0x5d, 0x26, 0x1f, 0xc2, 0x9c, 0x5c, 0x20, 0x7c, 0x3b, 0xe1, 0x13, 0xc7, 0x97, 0xc6, 0x95,
- 0xa4, 0xa5, 0x81, 0x68, 0x09, 0xd3, 0x37, 0x2b, 0x16, 0x45, 0x58, 0xfe, 0xe7, 0x67, 0x39, 0x90,
- 0x0f, 0xe0, 0xb4, 0x48, 0xff, 0xaa, 0xac, 0x8a, 0xba, 0x4b, 0x77, 0x85, 0x54, 0xf0, 0x62, 0x6c,
- 0xf4, 0xec, 0x86, 0xd2, 0x1c, 0x93, 0xee, 0xae, 0x3e, 0x67, 0xce, 0x7b, 0x09, 0xf0, 0xe8, 0x4a,
- 0xfb, 0x77, 0x52, 0x60, 0x1c, 0x3f, 0x5e, 0x28, 0xc7, 0x46, 0x07, 0x9c, 0xc9, 0xb1, 0xca, 0xe8,
- 0x5d, 0x84, 0x29, 0x97, 0xee, 0xba, 0xd4, 0xdb, 0xaf, 0xab, 0xa9, 0xf0, 0x27, 0x05, 0x50, 0x0e,
- 0x8c, 0x74, 0x34, 0x1f, 0x42, 0x3d, 0x9e, 0xfb, 0xce, 0x51, 0xe1, 0x39, 0xae, 0xd8, 0x14, 0x44,
- 0xc6, 0xad, 0x60, 0x03, 0x49, 0x9c, 0x87, 0x30, 0x0f, 0x7f, 0x4a, 0xc9, 0xc3, 0x7f, 0x27, 0x9b,
- 0x4b, 0xe7, 0x33, 0xa6, 0x70, 0x87, 0xdf, 0xb5, 0x5b, 0xd4, 0xf8, 0xf5, 0x14, 0x2c, 0xf6, 0x1f,
- 0x3c, 0xf2, 0xa1, 0xf2, 0xc0, 0x93, 0xe1, 0xd1, 0xc0, 0x8e, 0x19, 0x6f, 0x55, 0x17, 0x2e, 0x3c,
- 0xb4, 0xa3, 0x99, 0x4f, 0x05, 0xcb, 0x27, 0xd1, 0x52, 0xbf, 0x25, 0xf5, 0x43, 0x4c, 0xb2, 0xba,
- 0x7f, 0x9d, 0x5c, 0x81, 0x31, 0xae, 0x12, 0x92, 0x0d, 0x9d, 0xd1, 0x1a, 0x7a, 0xff, 0xba, 0x29,
- 0xcb, 0x8d, 0x6f, 0xa7, 0x82, 0x4b, 0x71, 0xb4, 0xf9, 0xf7, 0xaf, 0x93, 0xcf, 0x0c, 0xf7, 0x54,
- 0x93, 0x93, 0x4f, 0x35, 0xc1, 0x33, 0xcd, 0x67, 0xb5, 0x67, 0x9a, 0x97, 0x06, 0x8f, 0x93, 0x10,
- 0xbf, 0xa3, 0xb9, 0xe9, 0xfe, 0x79, 0x0a, 0xce, 0x0f, 0xa4, 0x20, 0xe7, 0x20, 0x57, 0xac, 0x56,
- 0x36, 0xc3, 0x99, 0x65, 0x5f, 0x8b, 0x84, 0x90, 0xdb, 0x30, 0xbe, 0x6c, 0x79, 0x76, 0x83, 0x2d,
- 0xe0, 0x44, 0x81, 0x22, 0xc6, 0x36, 0x40, 0x5f, 0x7d, 0xce, 0x0c, 0x69, 0x49, 0x1d, 0x66, 0xf1,
- 0x2b, 0x88, 0xe5, 0x7e, 0x8a, 0x1e, 0x3b, 0x31, 0x86, 0x31, 0x32, 0xb6, 0xc3, 0xc4, 0x80, 0xd1,
- 0x8f, 0xef, 0x81, 0x94, 0x33, 0xfa, 0x37, 0xf0, 0x04, 0x41, 0x15, 0x2e, 0x43, 0xae, 0x2a, 0x2f,
- 0xc6, 0x4a, 0xea, 0x47, 0x79, 0x09, 0x36, 0x83, 0x52, 0xe3, 0xaf, 0xa6, 0xe4, 0xd9, 0x70, 0x7c,
- 0x47, 0x94, 0xb8, 0xa9, 0xcd, 0xc1, 0x71, 0x53, 0x9b, 0x1f, 0x33, 0x6e, 0xaa, 0xf1, 0x4b, 0x22,
- 0xe4, 0x51, 0xa5, 0x59, 0x8d, 0x04, 0xcd, 0x7f, 0xd2, 0x87, 0xe7, 0x15, 0x6d, 0x75, 0x5e, 0x54,
- 0x02, 0x30, 0xc7, 0xeb, 0xea, 0xff, 0xfe, 0xac, 0x2c, 0xd5, 0x7f, 0x9a, 0x86, 0x73, 0x83, 0xc8,
- 0x13, 0xe3, 0xfb, 0xa7, 0x4e, 0x16, 0xdf, 0xff, 0x0a, 0xe4, 0x38, 0x4c, 0xcf, 0x53, 0x26, 0x48,
- 0xd9, 0x80, 0xcb, 0x62, 0x72, 0x11, 0x46, 0x8b, 0xa5, 0x5a, 0x18, 0x6c, 0x16, 0x5f, 0x4a, 0xac,
- 0x86, 0x87, 0x3a, 0x78, 0x51, 0x44, 0xbe, 0x12, 0x8f, 0xaf, 0x2c, 0xa2, 0xcc, 0x3e, 0xaf, 0x0c,
- 0x48, 0x2c, 0x1a, 0x19, 0xb6, 0x37, 0x8c, 0x9e, 0x25, 0x02, 0xd2, 0x98, 0xf1, 0x58, 0xcd, 0x06,
- 0x8c, 0x56, 0x5d, 0xea, 0x51, 0x5f, 0x7d, 0xc5, 0xe8, 0x22, 0xc4, 0x14, 0x25, 0xe2, 0x8d, 0xc1,
- 0x3a, 0xe4, 0x76, 0xe2, 0xa3, 0xaa, 0x1b, 0x0d, 0x3e, 0x4a, 0x30, 0xb0, 0xa9, 0xa0, 0x18, 0xdf,
- 0x4c, 0xc1, 0x7c, 0x52, 0xb3, 0xc8, 0x39, 0xc8, 0x76, 0x12, 0x23, 0x43, 0x77, 0xb8, 0xb5, 0xea,
- 0x04, 0xe6, 0x88, 0xe2, 0x19, 0xfe, 0xd5, 0xa7, 0x1b, 0x05, 0x6c, 0x02, 0xfb, 0x21, 0x92, 0xff,
- 0x17, 0xe4, 0x66, 0x9b, 0x89, 0xc5, 0x92, 0xc6, 0xff, 0x8c, 0x22, 0x40, 0xa5, 0x59, 0xdd, 0xe8,
- 0xf2, 0xe0, 0x56, 0x37, 0x20, 0xcb, 0x9a, 0x15, 0x59, 0x8c, 0x6c, 0x39, 0x14, 0xef, 0xad, 0x09,
- 0x24, 0xde, 0x2a, 0x26, 0x27, 0x9b, 0x88, 0x6c, 0x6c, 0xc3, 0xb4, 0x8e, 0x41, 0x56, 0xf4, 0x70,
- 0x08, 0x61, 0xfa, 0xea, 0x65, 0xc7, 0xe1, 0xe6, 0x03, 0xcb, 0x67, 0xbf, 0x7b, 0x54, 0x00, 0xf6,
- 0x93, 0xd3, 0x24, 0x85, 0x4b, 0x30, 0x7e, 0x2a, 0x0d, 0xf3, 0xa1, 0x19, 0xb2, 0xfc, 0x24, 0x9e,
- 0x59, 0x9b, 0xb8, 0xa2, 0x66, 0xb3, 0x55, 0x88, 0x65, 0x88, 0x95, 0x1d, 0x1c, 0x60, 0x2a, 0x72,
- 0x1b, 0x16, 0xfa, 0xe1, 0x93, 0xd7, 0x62, 0x39, 0x1c, 0x85, 0xbb, 0x5c, 0x90, 0xec, 0x51, 0x49,
- 0xe9, 0xf8, 0x8f, 0x52, 0xb0, 0x28, 0x1e, 0xbd, 0xef, 0x59, 0x76, 0x07, 0xf3, 0x56, 0x37, 0xe8,
- 0xd3, 0xb1, 0xe9, 0xbc, 0xad, 0x6d, 0x4b, 0x2f, 0xeb, 0xb6, 0x0d, 0xb1, 0xda, 0xfa, 0xf7, 0x96,
- 0x5c, 0x41, 0xc7, 0xc8, 0x06, 0x5f, 0xbc, 0x59, 0x6e, 0x43, 0xdf, 0x61, 0x00, 0xd5, 0x86, 0x1e,
- 0x31, 0x8c, 0xbf, 0x04, 0x2f, 0x0c, 0xae, 0x80, 0x7c, 0x19, 0xa6, 0x8a, 0x7b, 0xb4, 0xe3, 0x6f,
- 0x75, 0xf7, 0x5c, 0xab, 0x49, 0xe5, 0x55, 0x5f, 0x6a, 0xe8, 0xd5, 0x32, 0xee, 0x0c, 0x2a, 0x6c,
- 0xba, 0x19, 0xbc, 0xde, 0x13, 0x44, 0x9a, 0x65, 0x89, 0xca, 0xcd, 0xf8, 0x46, 0x0a, 0x48, 0x9c,
- 0x07, 0xb9, 0x09, 0x93, 0x5b, 0x9b, 0xa5, 0x9a, 0x6f, 0xb9, 0xfe, 0xaa, 0xd3, 0x73, 0x85, 0x93,
- 0x25, 0x37, 0xf1, 0xf5, 0x1b, 0x6c, 0x67, 0x70, 0xfd, 0xfa, 0xbe, 0xd3, 0x73, 0x4d, 0x0d, 0x0f,
- 0x23, 0x96, 0x52, 0x7a, 0xd0, 0xb4, 0x0e, 0xf5, 0x88, 0xa5, 0x02, 0xa6, 0x45, 0x2c, 0x15, 0x30,
- 0xe3, 0x6f, 0xa7, 0xe0, 0x79, 0xa9, 0x0d, 0x6f, 0x26, 0xb4, 0xa5, 0x84, 0x8e, 0x2c, 0xae, 0x0c,
- 0x32, 0x31, 0x48, 0x36, 0x9d, 0x95, 0xbe, 0x5e, 0xd8, 0x40, 0x14, 0x52, 0x39, 0x2d, 0x26, 0xed,
- 0xf7, 0x9d, 0xee, 0x10, 0xce, 0x5e, 0xf9, 0x60, 0x46, 0x7d, 0xa7, 0x8b, 0x2c, 0x90, 0xd2, 0xa0,
- 0x30, 0xaf, 0x36, 0x4e, 0xb6, 0x98, 0xdc, 0x83, 0x31, 0xe1, 0x85, 0x1b, 0xd1, 0x31, 0x0c, 0xe8,
- 0xd3, 0xf2, 0x8c, 0xf4, 0x28, 0x13, 0x41, 0x0e, 0x4c, 0xc9, 0xc3, 0xf8, 0xc9, 0x14, 0x4c, 0x30,
- 0xe1, 0x01, 0xe3, 0xfe, 0x3c, 0xe9, 0x92, 0xd6, 0xe5, 0x40, 0xa9, 0x78, 0x0a, 0xd8, 0x0f, 0x75,
- 0xb8, 0xbe, 0x09, 0x33, 0x11, 0x02, 0x62, 0xa0, 0x2f, 0x41, 0xcb, 0xe6, 0xe9, 0xcf, 0xa5, 0xd6,
- 0x46, 0x83, 0x19, 0xff, 0x4a, 0x0a, 0xe6, 0x37, 0x0e, 0x7c, 0xab, 0xd2, 0xee, 0x3a, 0xae, 0x6f,
- 0xf6, 0x5a, 0xf2, 0x7b, 0x67, 0x02, 0x91, 0x7c, 0x56, 0xe1, 0x76, 0xce, 0x5c, 0x20, 0x12, 0x30,
- 0x33, 0x28, 0x25, 0xab, 0x90, 0x13, 0xe7, 0x8b, 0x27, 0x62, 0x13, 0xc8, 0x57, 0x43, 0x9d, 0xb1,
- 0x40, 0x62, 0x3d, 0xc1, 0x2d, 0x4c, 0xd0, 0x98, 0x01, 0xb5, 0xf1, 0x27, 0x29, 0x38, 0xd3, 0x87,
- 0x86, 0xbc, 0x0b, 0x23, 0x68, 0xae, 0x25, 0x66, 0xef, 0x5c, 0x9f, 0x2a, 0xfc, 0xc6, 0xfe, 0xfd,
- 0xeb, 0xfc, 0x20, 0x6a, 0xb3, 0x1f, 0x26, 0xa7, 0x22, 0x1f, 0xc2, 0x78, 0xb1, 0xd9, 0x14, 0xf7,
- 0x92, 0xb4, 0x76, 0x2f, 0xe9, 0x53, 0xe3, 0xd5, 0x00, 0x9f, 0xdf, 0x4b, 0xb8, 0xe1, 0x40, 0xb3,
- 0x59, 0x17, 0xa6, 0x68, 0x21, 0xbf, 0xc5, 0x77, 0x60, 0x5a, 0x47, 0x3e, 0xd1, 0xbd, 0xe4, 0xdb,
- 0x29, 0xc8, 0xeb, 0x6d, 0xf8, 0x64, 0x7c, 0xe1, 0x92, 0xa6, 0xf9, 0x98, 0x45, 0xf5, 0x33, 0x69,
- 0x38, 0x95, 0x38, 0xc2, 0xe4, 0x0d, 0x18, 0x2d, 0x76, 0xbb, 0x95, 0xb2, 0x58, 0x55, 0x42, 0xe0,
- 0x41, 0xad, 0x9a, 0x76, 0x6d, 0xe3, 0x48, 0xe4, 0x06, 0xe4, 0x70, 0x65, 0x32, 0x82, 0x74, 0x18,
- 0x25, 0x80, 0x2b, 0xa7, 0x23, 0x51, 0x02, 0x24, 0x22, 0xb9, 0x05, 0xd3, 0xc2, 0x2d, 0xc6, 0xa4,
- 0x7b, 0xf4, 0x51, 0x10, 0xae, 0x0a, 0x23, 0x6a, 0x49, 0x27, 0x9a, 0xba, 0xcb, 0xcb, 0x54, 0xc7,
- 0x10, 0x9d, 0x0a, 0x73, 0x8a, 0x32, 0x9e, 0x2a, 0x27, 0x1e, 0xaa, 0x80, 0xe7, 0x14, 0xc5, 0x46,
- 0xf4, 0xe1, 0x15, 0xa3, 0x0c, 0xa6, 0xab, 0xe8, 0x79, 0xf6, 0x5e, 0xa7, 0x4d, 0x3b, 0xfe, 0x27,
- 0x37, 0x5d, 0x61, 0x1d, 0x43, 0x4d, 0xd7, 0xb7, 0xb2, 0xfc, 0x63, 0x8e, 0x92, 0x1d, 0x93, 0x36,
- 0xbb, 0x0c, 0x63, 0xdc, 0x21, 0x47, 0x7e, 0x19, 0xe7, 0x13, 0x9b, 0xc0, 0x71, 0xee, 0x5f, 0xe7,
- 0xe2, 0x0b, 0xb7, 0x1b, 0xf3, 0x4c, 0x49, 0x4a, 0xee, 0xc3, 0x44, 0xa9, 0x45, 0xad, 0x4e, 0xaf,
- 0xcb, 0x36, 0xe9, 0x21, 0x34, 0x14, 0x0b, 0xa2, 0x2f, 0x93, 0x0d, 0x4e, 0x56, 0xf7, 0xed, 0x36,
- 0xc5, 0x9d, 0x5c, 0x65, 0x44, 0x36, 0x03, 0x53, 0x92, 0x2c, 0x2a, 0xbf, 0x3e, 0x35, 0x60, 0x7c,
- 0xa2, 0x40, 0xa4, 0xd3, 0xed, 0xa4, 0x84, 0xad, 0x49, 0x1d, 0xa6, 0xd7, 0x2c, 0xcf, 0xdf, 0x74,
- 0xad, 0x8e, 0x87, 0x3e, 0xf5, 0x43, 0x38, 0x3a, 0xca, 0xd4, 0x5d, 0x33, 0xe8, 0xc8, 0xe2, 0x07,
- 0xa4, 0xd8, 0xe6, 0x08, 0x3b, 0x26, 0x2f, 0xdd, 0xb2, 0x3b, 0x56, 0xcb, 0xfe, 0xba, 0xb4, 0xb8,
- 0xe3, 0xf2, 0xd2, 0xae, 0x04, 0x9a, 0x61, 0xb9, 0xf1, 0xa5, 0xd8, 0xbc, 0xf1, 0x56, 0x4e, 0xc0,
- 0x98, 0x30, 0xb2, 0xe6, 0x46, 0xc7, 0xd5, 0x95, 0xf5, 0x72, 0x65, 0xfd, 0x76, 0x3e, 0x45, 0xa6,
- 0x01, 0xaa, 0xe6, 0x46, 0x69, 0xa5, 0x56, 0x63, 0xbf, 0xd3, 0xec, 0xb7, 0xb0, 0x48, 0xbe, 0xb5,
- 0xb5, 0x96, 0xcf, 0x28, 0x46, 0xc9, 0x59, 0xe3, 0x1f, 0xa6, 0xe0, 0x74, 0xf2, 0x54, 0x92, 0x4d,
- 0x40, 0xb3, 0x74, 0xa1, 0x57, 0xbc, 0x39, 0x70, 0xde, 0x13, 0xc1, 0x51, 0xf3, 0x76, 0x9f, 0x9b,
- 0x4d, 0xa7, 0xe5, 0xe3, 0x57, 0x98, 0xbf, 0xca, 0x6e, 0x1a, 0x25, 0x58, 0xe8, 0xc7, 0x43, 0xef,
- 0xea, 0x0c, 0x4c, 0x14, 0xab, 0xd5, 0xb5, 0x4a, 0xa9, 0xb8, 0x59, 0xd9, 0x58, 0xcf, 0xa7, 0xc8,
- 0x38, 0x8c, 0xdc, 0x36, 0x37, 0xb6, 0xaa, 0xf9, 0xb4, 0xf1, 0xd7, 0x52, 0x30, 0x55, 0xe9, 0xf8,
- 0x74, 0x8f, 0x5b, 0x30, 0x3c, 0xe9, 0xc7, 0xf7, 0x39, 0xed, 0xe3, 0x5b, 0x08, 0x1c, 0x38, 0x82,
- 0x0a, 0x86, 0xfa, 0xf2, 0xfe, 0x71, 0x0a, 0x66, 0x63, 0x34, 0xa4, 0x06, 0x63, 0xc5, 0xed, 0xda,
- 0x46, 0xa5, 0x5c, 0x12, 0x2d, 0x93, 0x52, 0xb9, 0x80, 0xc6, 0x6b, 0xe1, 0xf6, 0x91, 0x0f, 0xbd,
- 0xba, 0x63, 0x37, 0x95, 0x00, 0xfc, 0xab, 0xcf, 0x99, 0x92, 0x13, 0x9e, 0x64, 0x5f, 0xef, 0xb9,
- 0x14, 0xd9, 0xa6, 0x35, 0x8d, 0x66, 0x00, 0x8f, 0x33, 0xe6, 0x09, 0xb5, 0x59, 0x79, 0x9c, 0x75,
- 0xc8, 0x6f, 0x79, 0x0a, 0x26, 0xc4, 0xad, 0x05, 0x2f, 0x04, 0x3f, 0x9e, 0x82, 0x85, 0x7e, 0x6d,
- 0x65, 0x17, 0x21, 0xdd, 0x58, 0xfa, 0x74, 0x10, 0x8d, 0x4d, 0xb7, 0x92, 0x96, 0x68, 0xe4, 0x5d,
- 0x98, 0xe0, 0x99, 0xfc, 0x6a, 0x37, 0xb6, 0xcc, 0x8a, 0x58, 0x20, 0xe8, 0x4e, 0x29, 0x92, 0x8e,
- 0x7b, 0x37, 0x22, 0x19, 0xa8, 0x55, 0x7c, 0xe3, 0x47, 0x53, 0xb0, 0xd8, 0xbf, 0x8b, 0xec, 0x8c,
- 0xd9, 0x64, 0x92, 0x79, 0x68, 0x6d, 0x8a, 0x67, 0x0c, 0x4a, 0xeb, 0x11, 0x73, 0xd3, 0x00, 0x91,
- 0x11, 0xfd, 0xbf, 0xd4, 0x5d, 0x5f, 0x6f, 0x1b, 0xc7, 0x11, 0xd7, 0xf1, 0x5f, 0xa4, 0x91, 0x64,
- 0x9d, 0xd6, 0x8e, 0xac, 0xca, 0xb2, 0xe2, 0x12, 0xa9, 0x51, 0x5f, 0x1b, 0xa7, 0x49, 0x1b, 0x24,
- 0x4a, 0x91, 0x06, 0x27, 0x72, 0x29, 0xd2, 0xba, 0x3f, 0xf4, 0xdd, 0xd1, 0x8a, 0xdd, 0x3f, 0x07,
- 0x5a, 0x3a, 0x4b, 0x6c, 0xa9, 0x23, 0x23, 0x52, 0x71, 0xdd, 0xb7, 0xbe, 0x14, 0x28, 0x8a, 0x02,
- 0x45, 0x5f, 0xfb, 0xd0, 0x97, 0xbc, 0xf4, 0x33, 0xf4, 0x0b, 0x04, 0x28, 0x0a, 0xe4, 0x13, 0x14,
- 0xad, 0x81, 0x7e, 0x84, 0xbe, 0xe4, 0xa9, 0xd8, 0xd9, 0xdd, 0xbb, 0xbd, 0x23, 0xa9, 0x48, 0x8e,
- 0xd1, 0x22, 0x6f, 0xbc, 0xd9, 0xd9, 0xe5, 0xde, 0xfe, 0x99, 0xdb, 0x99, 0x9d, 0xf9, 0x4d, 0x2e,
- 0xaf, 0xb9, 0x9a, 0xcf, 0x22, 0x5b, 0x49, 0x32, 0x56, 0xff, 0x54, 0x80, 0x35, 0xb6, 0x7c, 0xfa,
- 0xd1, 0x68, 0x64, 0x9e, 0x8d, 0x8f, 0xa3, 0x78, 0x2c, 0x0e, 0x54, 0xe4, 0x5d, 0xa8, 0x1c, 0x5f,
- 0xce, 0x16, 0xc8, 0xd9, 0x09, 0x01, 0x14, 0xc9, 0xf2, 0xba, 0x9f, 0xfd, 0x26, 0x37, 0x41, 0xc9,
- 0x1f, 0x82, 0x12, 0x75, 0xc9, 0x5b, 0x18, 0x26, 0x59, 0x44, 0xde, 0x83, 0x32, 0xea, 0xfe, 0x42,
- 0x30, 0xca, 0x03, 0xed, 0xf4, 0x9e, 0xa1, 0x65, 0xc0, 0xe3, 0x15, 0xc8, 0x9b, 0x00, 0x29, 0xe6,
- 0x97, 0x90, 0x7c, 0x52, 0x89, 0x4e, 0x60, 0xbf, 0xbc, 0x85, 0x93, 0x27, 0x5d, 0x01, 0xa4, 0x65,
- 0xc0, 0xaa, 0x1c, 0x92, 0xa1, 0x8c, 0x6a, 0xe6, 0x96, 0x08, 0x6f, 0x85, 0x17, 0xb4, 0x86, 0x22,
- 0xb2, 0xb9, 0xfa, 0xef, 0x02, 0x2c, 0xec, 0xb3, 0x63, 0x02, 0x2a, 0xbf, 0xe7, 0x2b, 0xd3, 0x6f,
- 0xc3, 0xa2, 0x35, 0xe8, 0x0a, 0xcb, 0xfd, 0x48, 0x00, 0x2b, 0xa0, 0xcb, 0x65, 0x7f, 0xd0, 0x95,
- 0x97, 0x00, 0x23, 0x4f, 0x65, 0xfa, 0x12, 0x77, 0xd1, 0x7b, 0x50, 0xe1, 0xf7, 0xd6, 0xc2, 0x4c,
- 0x23, 0x0f, 0x8a, 0x49, 0x8f, 0xee, 0xf2, 0x62, 0xc5, 0xd8, 0xcc, 0x6f, 0xbe, 0xd5, 0x53, 0x8b,
- 0xc0, 0x55, 0x50, 0x54, 0xfd, 0xf2, 0xc5, 0x54, 0x7d, 0x25, 0x7e, 0xb4, 0x72, 0x91, 0xf8, 0xd1,
- 0x8d, 0x6d, 0x58, 0x54, 0xfa, 0x73, 0xa9, 0x73, 0xe3, 0xaf, 0x0b, 0xb0, 0x8c, 0x6f, 0x95, 0xdc,
- 0x12, 0x7d, 0x3d, 0x0d, 0x17, 0xef, 0x67, 0x0c, 0x17, 0xeb, 0xea, 0x7c, 0xf1, 0x37, 0x3b, 0xc7,
- 0x62, 0x71, 0x0f, 0x56, 0x27, 0x18, 0xc9, 0x3b, 0x50, 0x66, 0xdd, 0x97, 0x8a, 0x9e, 0x9e, 0x5f,
- 0x01, 0x29, 0xd6, 0x08, 0x7b, 0xf1, 0x91, 0xc7, 0xb9, 0xab, 0xff, 0xd1, 0x60, 0x49, 0x80, 0xc0,
- 0xc5, 0x4f, 0x06, 0x5f, 0x3a, 0x9c, 0xb7, 0xf3, 0xc3, 0xc9, 0x83, 0x1f, 0xc4, 0x70, 0xfe, 0xaf,
- 0x07, 0x71, 0x3b, 0x33, 0x88, 0xd7, 0x93, 0xc8, 0x63, 0xf9, 0x3a, 0xe7, 0x8c, 0xe1, 0x5f, 0x11,
- 0x8b, 0x23, 0xcb, 0x48, 0x7e, 0x06, 0x0b, 0x4e, 0xf4, 0x34, 0xa3, 0x2f, 0xdd, 0x9e, 0xd1, 0xe8,
- 0xdd, 0x84, 0x91, 0xef, 0x29, 0xfc, 0xd4, 0xc4, 0xd1, 0xd3, 0x70, 0xe2, 0x12, 0x27, 0x6d, 0x92,
- 0xa9, 0x4c, 0xd9, 0x6a, 0x97, 0x59, 0xfa, 0xc2, 0xc5, 0x0e, 0xe3, 0x79, 0xfe, 0x52, 0x04, 0x48,
- 0xbd, 0x93, 0xd8, 0x06, 0x8c, 0x32, 0x50, 0xa9, 0xc2, 0x72, 0x8c, 0x24, 0x75, 0x8d, 0x0b, 0x12,
- 0xb9, 0x2d, 0x4c, 0xa2, 0x85, 0xd9, 0x91, 0xe1, 0x68, 0x1c, 0xad, 0x09, 0xef, 0x9f, 0xc3, 0xa8,
- 0xdf, 0xe5, 0xb2, 0xb8, 0x88, 0xd9, 0xfa, 0xaf, 0xa5, 0xd4, 0x19, 0xd9, 0x3c, 0xd0, 0x47, 0xa8,
- 0xce, 0x18, 0x26, 0x3c, 0xfe, 0x4a, 0x2f, 0xee, 0xf1, 0x57, 0x7e, 0x01, 0x8f, 0xbf, 0xca, 0x05,
- 0x3d, 0xfe, 0xda, 0xb0, 0xd0, 0x8b, 0x3f, 0x89, 0xe2, 0xf1, 0xe0, 0xf4, 0x19, 0xfa, 0x03, 0xa5,
- 0x86, 0x2c, 0x36, 0xd4, 0x2d, 0x59, 0xc6, 0xe7, 0x1b, 0x3f, 0x98, 0x09, 0xbf, 0x3a, 0xdd, 0x09,
- 0x51, 0xb8, 0x30, 0x7c, 0x51, 0x00, 0x32, 0xd9, 0x00, 0x79, 0x1f, 0x16, 0xb9, 0x08, 0x0e, 0x4f,
- 0x47, 0x1f, 0x0b, 0x77, 0x31, 0x1e, 0x37, 0xa5, 0x90, 0xd5, 0xb8, 0x29, 0x4e, 0xf6, 0x46, 0x1f,
- 0xf7, 0xc9, 0x4f, 0xe1, 0x2a, 0x4e, 0xc0, 0x30, 0x3a, 0xed, 0x0d, 0x0e, 0x43, 0x44, 0xae, 0xe8,
- 0xf6, 0x05, 0x36, 0xf7, 0x1b, 0x98, 0x44, 0x62, 0xb2, 0x78, 0xc6, 0x44, 0xa1, 0x57, 0x56, 0x1b,
- 0x39, 0xdb, 0x9c, 0x91, 0x04, 0xa0, 0xab, 0xf5, 0x9f, 0x9c, 0xf5, 0xfb, 0x62, 0xee, 0x0d, 0xcc,
- 0xb0, 0x9b, 0x2b, 0x9b, 0xd1, 0xf0, 0x95, 0xb4, 0xe1, 0xc6, 0x59, 0xbf, 0x4f, 0xde, 0x05, 0x18,
- 0xc4, 0xe1, 0x49, 0x6f, 0x34, 0xe2, 0xd7, 0x09, 0x89, 0x47, 0x65, 0x4a, 0x55, 0x87, 0x71, 0x10,
- 0xdb, 0x9c, 0x48, 0x7e, 0x00, 0xe8, 0x6e, 0x8d, 0x71, 0x08, 0xb8, 0x02, 0xca, 0x02, 0x6d, 0x4f,
- 0x12, 0xb3, 0xd3, 0x79, 0x14, 0xf9, 0xbd, 0x5f, 0x49, 0xff, 0x91, 0x47, 0xb0, 0x2a, 0xe2, 0xac,
- 0xf6, 0x7b, 0xe3, 0x63, 0x71, 0xfa, 0xfd, 0x2a, 0x47, 0x67, 0xe5, 0xf8, 0xfb, 0xdb, 0x12, 0x80,
- 0xb9, 0xef, 0xcb, 0x10, 0xbf, 0x3b, 0x50, 0x66, 0x67, 0x7a, 0x69, 0x1b, 0x40, 0xcb, 0x2a, 0xb6,
- 0xab, 0x5a, 0x56, 0x91, 0x83, 0xed, 0x57, 0x2f, 0x3a, 0x42, 0xf3, 0x54, 0x21, 0x35, 0x24, 0x9c,
- 0x72, 0x52, 0xe6, 0x0c, 0xc9, 0x49, 0xc4, 0x02, 0x48, 0x83, 0xee, 0x84, 0x96, 0xb9, 0x9a, 0x46,
- 0xaf, 0x88, 0x02, 0x01, 0xa3, 0x96, 0x06, 0xee, 0xa9, 0xcb, 0x27, 0x65, 0x23, 0x7b, 0x50, 0x0a,
- 0xba, 0x89, 0xbf, 0xe0, 0x8c, 0x50, 0xc4, 0x5b, 0x02, 0x3b, 0x3d, 0x0d, 0x47, 0xbc, 0x32, 0xee,
- 0x66, 0x52, 0x4c, 0x60, 0x23, 0x84, 0x42, 0x45, 0xe4, 0xc5, 0x99, 0x11, 0x97, 0x2e, 0xd2, 0xe2,
- 0x08, 0x34, 0x1a, 0x24, 0xaa, 0xa7, 0x0e, 0x91, 0x01, 0xe7, 0x6d, 0x28, 0xfa, 0xbe, 0x2d, 0x1c,
- 0xf0, 0x97, 0x53, 0x8d, 0xc1, 0xf7, 0x6d, 0x99, 0xfb, 0xeb, 0x44, 0xa9, 0xc6, 0x98, 0xc9, 0x0f,
- 0x61, 0x51, 0x39, 0x10, 0x8b, 0xd0, 0x15, 0x1c, 0x83, 0x5e, 0x4a, 0xce, 0x9c, 0xab, 0x53, 0x32,
- 0xb1, 0x40, 0xdf, 0x3b, 0x7b, 0x1c, 0x99, 0xc3, 0x21, 0xfa, 0xba, 0x7d, 0x12, 0x9d, 0x72, 0x88,
- 0xb7, 0xf9, 0x14, 0xc8, 0x25, 0xec, 0x0e, 0x87, 0xe1, 0xa1, 0x2c, 0x55, 0xed, 0x23, 0xf9, 0x9a,
- 0xd5, 0x48, 0x9d, 0x20, 0xf6, 0x95, 0xcc, 0x2a, 0x09, 0xf8, 0x95, 0x94, 0x4a, 0x42, 0xaa, 0x1a,
- 0xbc, 0x39, 0x25, 0x74, 0x12, 0xaf, 0x9e, 0x94, 0xd0, 0xc9, 0x4c, 0xc0, 0xe4, 0xa7, 0x25, 0x25,
- 0x24, 0x5f, 0x8c, 0xdc, 0x07, 0x00, 0xf7, 0x06, 0xbd, 0xd8, 0x8e, 0xc6, 0xc7, 0x83, 0x43, 0x25,
- 0x82, 0x73, 0xf1, 0xe7, 0x83, 0x5e, 0x1c, 0x9e, 0x20, 0xf9, 0x8b, 0x7f, 0xbc, 0xa6, 0x30, 0x79,
- 0xca, 0x6f, 0xf2, 0x5d, 0x58, 0x60, 0x4f, 0x41, 0xea, 0x80, 0xc1, 0x8d, 0x7e, 0x58, 0x5b, 0x64,
- 0xfc, 0x4b, 0x18, 0xc8, 0x36, 0xa2, 0x26, 0xf6, 0x86, 0x63, 0xe5, 0x30, 0x2a, 0x21, 0x12, 0x7b,
- 0xc3, 0x71, 0x1e, 0x65, 0x45, 0x61, 0x26, 0xcd, 0xa4, 0xeb, 0x12, 0x77, 0x53, 0x80, 0x33, 0xa2,
- 0x65, 0x4b, 0xac, 0x8c, 0x50, 0xc2, 0x3b, 0xa8, 0x19, 0x12, 0x72, 0xd5, 0xb0, 0x13, 0x7e, 0xb3,
- 0xce, 0xaf, 0x22, 0xc4, 0x37, 0x81, 0x77, 0x62, 0x74, 0x7c, 0x18, 0x1e, 0x20, 0x39, 0xd3, 0x89,
- 0x84, 0x99, 0xec, 0xc0, 0x0a, 0x8f, 0x33, 0x4a, 0xf0, 0xbb, 0xc5, 0xf7, 0x01, 0x25, 0x51, 0x0a,
- 0xf0, 0xad, 0xfe, 0x7d, 0xae, 0x02, 0x69, 0x40, 0x19, 0x15, 0x32, 0x11, 0xec, 0x71, 0x43, 0xd5,
- 0x43, 0xf3, 0xab, 0x1e, 0xa5, 0x00, 0x6a, 0xa0, 0xaa, 0x14, 0x40, 0x56, 0xf2, 0x11, 0x00, 0x8d,
- 0x4f, 0x07, 0xfd, 0x3e, 0x02, 0x90, 0xcc, 0xa3, 0x3a, 0x73, 0x33, 0xbb, 0x7b, 0xb0, 0x95, 0x94,
- 0x49, 0xe6, 0x6a, 0x67, 0xcf, 0x61, 0x0e, 0xa6, 0x44, 0x69, 0xab, 0xda, 0x82, 0x0a, 0xdf, 0x3a,
- 0x08, 0xe6, 0x23, 0x90, 0x02, 0x15, 0x28, 0x18, 0x0e, 0xe6, 0x23, 0xe8, 0x93, 0x60, 0x3e, 0x4a,
- 0x85, 0xea, 0x1e, 0x5c, 0x9b, 0xf6, 0x62, 0x19, 0x15, 0x52, 0xbb, 0xa8, 0x0a, 0xf9, 0xe7, 0x22,
- 0x2c, 0x61, 0x6b, 0x52, 0x66, 0x9a, 0xb0, 0xec, 0x9f, 0x3d, 0x4e, 0x82, 0xe2, 0xa4, 0xec, 0xe4,
- 0x69, 0xf2, 0xd5, 0x02, 0xf5, 0x92, 0x28, 0x53, 0x83, 0x50, 0xb8, 0x22, 0xe5, 0xb6, 0xc8, 0x60,
- 0x50, 0x48, 0x71, 0x74, 0x64, 0xb8, 0xf6, 0x64, 0xfe, 0x82, 0x5c, 0xa5, 0x54, 0x7a, 0x17, 0x2f,
- 0x23, 0xbd, 0x4b, 0x17, 0x92, 0xde, 0x3f, 0x86, 0x25, 0xf9, 0x6f, 0x28, 0x77, 0xcb, 0x5f, 0x4d,
- 0xee, 0x66, 0x1a, 0x23, 0x56, 0x22, 0x7f, 0x2b, 0xe7, 0xca, 0x5f, 0xbc, 0x79, 0x93, 0xbb, 0x6c,
- 0x22, 0x25, 0x99, 0x68, 0x03, 0x01, 0xbe, 0x77, 0x6b, 0xed, 0x17, 0xf8, 0xa6, 0xbd, 0x03, 0x0b,
- 0xd6, 0x40, 0x5e, 0xba, 0x28, 0xd6, 0xee, 0xbe, 0x24, 0xaa, 0x1f, 0xf7, 0x84, 0x33, 0xf9, 0x16,
- 0x15, 0x5f, 0xc6, 0xb7, 0x68, 0x1b, 0xa0, 0xcd, 0x43, 0x19, 0x52, 0x60, 0x5e, 0xdc, 0x32, 0x32,
- 0xe6, 0x21, 0x6b, 0x74, 0x57, 0x98, 0x99, 0x74, 0x12, 0xee, 0x19, 0xe6, 0xc1, 0xc1, 0xe0, 0x2c,
- 0x1e, 0x67, 0x32, 0x59, 0x88, 0xf0, 0xa7, 0xb0, 0x2b, 0xca, 0x54, 0xf1, 0x90, 0xab, 0xf6, 0x72,
- 0x27, 0x84, 0xdc, 0x4f, 0xfc, 0xca, 0xce, 0x4d, 0xec, 0x57, 0x9d, 0x18, 0xa1, 0x99, 0xde, 0x64,
- 0xd5, 0xbf, 0x69, 0x2a, 0x88, 0xd9, 0x0b, 0x4c, 0xf5, 0x7b, 0x00, 0xc9, 0xad, 0xb7, 0x9c, 0x6b,
- 0xae, 0xff, 0x24, 0x54, 0x75, 0x94, 0x53, 0x5e, 0xe5, 0x6d, 0x8a, 0x2f, 0xeb, 0x6d, 0x02, 0x58,
- 0x74, 0x7f, 0x31, 0xee, 0xa6, 0x6e, 0x12, 0xe0, 0x27, 0xe7, 0x4e, 0x94, 0x4c, 0x32, 0x01, 0x61,
- 0x7a, 0x6a, 0x9d, 0x99, 0x80, 0x30, 0xa9, 0x58, 0xbd, 0x0f, 0x2b, 0xaa, 0x0b, 0xf7, 0xb3, 0xf8,
- 0x80, 0xfc, 0x88, 0xa3, 0x2f, 0x68, 0x19, 0xcd, 0x40, 0x61, 0x62, 0x12, 0xf7, 0x59, 0x7c, 0xc0,
- 0x4f, 0x2b, 0xdd, 0xa7, 0x6a, 0x5f, 0x51, 0x67, 0xfb, 0x5c, 0x03, 0x32, 0xc9, 0xae, 0x4a, 0x13,
- 0xed, 0xff, 0x70, 0x16, 0xcc, 0x9d, 0xa1, 0x4a, 0x97, 0x39, 0x43, 0x19, 0x7f, 0xd0, 0x60, 0xa5,
- 0x65, 0xda, 0x02, 0x71, 0x8c, 0x5b, 0xef, 0xbf, 0x09, 0x37, 0x5b, 0xa6, 0x1d, 0xb6, 0x5d, 0xab,
- 0x55, 0x7b, 0x18, 0x4e, 0x05, 0x12, 0xb9, 0x09, 0xdf, 0x98, 0x64, 0x49, 0xad, 0xfc, 0x9b, 0xb0,
- 0x3e, 0x59, 0x2c, 0xc1, 0x46, 0xa6, 0x57, 0x96, 0xb8, 0x24, 0x45, 0xe3, 0x43, 0x58, 0x91, 0x18,
- 0x1c, 0x81, 0xe5, 0x23, 0x74, 0xd7, 0x0a, 0x2c, 0x3e, 0xa0, 0x5e, 0xab, 0xf1, 0x30, 0x6c, 0x74,
- 0x2c, 0x4b, 0x9f, 0x23, 0xcb, 0xb0, 0x20, 0x08, 0x35, 0x53, 0xd7, 0xc8, 0x12, 0xcc, 0xb7, 0x1c,
- 0x9f, 0xd6, 0x3a, 0x1e, 0xd5, 0x0b, 0xc6, 0x87, 0x70, 0x25, 0xcd, 0xd2, 0x8e, 0x46, 0xfa, 0x57,
- 0xa0, 0xe8, 0x99, 0xfb, 0xfa, 0x1c, 0x01, 0xa8, 0xb4, 0xf7, 0x6a, 0xfe, 0x5b, 0x6f, 0xe9, 0x1a,
- 0x59, 0x84, 0x57, 0x76, 0x6b, 0xed, 0x70, 0xcf, 0xf6, 0xf5, 0x02, 0x7b, 0x30, 0xf7, 0x7d, 0x7c,
- 0x28, 0x1a, 0xdf, 0x83, 0x55, 0x3c, 0x2b, 0x58, 0xbd, 0xd1, 0x38, 0x8a, 0xa3, 0x53, 0xec, 0xc3,
- 0x12, 0xcc, 0xfb, 0x11, 0xdb, 0xe4, 0xe3, 0x88, 0x77, 0xc0, 0x3e, 0xeb, 0x8f, 0x7b, 0xc3, 0x7e,
- 0xf4, 0x4b, 0x5d, 0x33, 0xb6, 0x61, 0xc5, 0x1b, 0x9c, 0x8d, 0x7b, 0xf1, 0x91, 0x3f, 0x66, 0x1c,
- 0x47, 0xcf, 0xc8, 0xab, 0xb0, 0xda, 0x71, 0x4c, 0x7b, 0xa7, 0xb5, 0xdb, 0x71, 0x3b, 0x7e, 0x68,
- 0x9b, 0x41, 0xad, 0xc9, 0xaf, 0x08, 0x6c, 0xd7, 0x0f, 0x42, 0x8f, 0xd6, 0xa8, 0x13, 0xe8, 0x9a,
- 0xf1, 0x3b, 0x0d, 0xae, 0x74, 0x46, 0xc2, 0xad, 0xb5, 0x83, 0x78, 0x12, 0xb7, 0x60, 0xb3, 0xe3,
- 0x53, 0x2f, 0x0c, 0xdc, 0x3d, 0xea, 0x84, 0x1d, 0xdf, 0xdc, 0xcd, 0xa3, 0xd8, 0xbc, 0x06, 0x37,
- 0x14, 0x0e, 0x8f, 0xd6, 0xdc, 0x07, 0xd4, 0x0b, 0xdb, 0xa6, 0xef, 0xef, 0xbb, 0x5e, 0x5d, 0xd7,
- 0xc8, 0x06, 0xac, 0x4d, 0x61, 0xb0, 0x1b, 0xa6, 0x5e, 0x98, 0x28, 0x73, 0xe8, 0xbe, 0x69, 0x85,
- 0x3b, 0x6e, 0xa0, 0x17, 0x0d, 0x9b, 0x7d, 0xe8, 0x10, 0xe8, 0x81, 0xc3, 0x74, 0xce, 0x43, 0xc9,
- 0x71, 0x1d, 0x9a, 0xbf, 0xc6, 0x59, 0x82, 0x79, 0xb3, 0xdd, 0xf6, 0xdc, 0x07, 0x38, 0xa1, 0x00,
- 0x95, 0x3a, 0x75, 0x58, 0xcf, 0x8a, 0xac, 0xa4, 0xed, 0xb9, 0xb6, 0x1b, 0xd0, 0xba, 0x5e, 0x32,
- 0x3c, 0xb9, 0x61, 0x64, 0xa3, 0x07, 0x03, 0x7e, 0x67, 0x52, 0xa7, 0x0d, 0xb3, 0x63, 0x05, 0x62,
- 0x40, 0x1e, 0x86, 0x1e, 0xbd, 0xdf, 0xa1, 0x7e, 0xe0, 0xeb, 0x1a, 0xd1, 0x61, 0xc9, 0xa1, 0xb4,
- 0xee, 0x87, 0x1e, 0x7d, 0xd0, 0xa2, 0xfb, 0x7a, 0x81, 0xb5, 0xc9, 0x7f, 0xb3, 0x7f, 0x30, 0x3e,
- 0xd5, 0x80, 0x70, 0x90, 0x0c, 0x09, 0xa7, 0x88, 0xf3, 0xb3, 0x05, 0x1b, 0x4d, 0x36, 0xb0, 0xf8,
- 0x6a, 0xb6, 0x5b, 0xcf, 0x0f, 0xd9, 0x1a, 0x90, 0x5c, 0xb9, 0xdb, 0x68, 0xe8, 0x1a, 0xb9, 0x01,
- 0x57, 0x73, 0xf4, 0xba, 0xe7, 0xb6, 0xf5, 0xc2, 0x46, 0x61, 0x5e, 0x23, 0xd7, 0x27, 0x0a, 0xf7,
- 0x28, 0x6d, 0xeb, 0x45, 0x36, 0x45, 0xb9, 0x02, 0xb9, 0x00, 0x79, 0xf5, 0x92, 0xf1, 0x1b, 0x0d,
- 0xd6, 0x78, 0x37, 0xe5, 0x6a, 0x4e, 0xba, 0xba, 0x09, 0xeb, 0x02, 0xcf, 0x67, 0x5a, 0x47, 0xaf,
- 0x81, 0x9e, 0x29, 0xe5, 0xdd, 0x7c, 0x15, 0x56, 0x33, 0x54, 0xec, 0x47, 0x81, 0xed, 0xd5, 0x0c,
- 0x79, 0x87, 0xfa, 0x41, 0x48, 0x1b, 0x0d, 0xd7, 0x0b, 0x78, 0x47, 0x8a, 0x46, 0x15, 0x56, 0x6b,
- 0xd1, 0xe9, 0x98, 0xe9, 0x20, 0xf1, 0xa8, 0x37, 0x88, 0xb1, 0x0b, 0xcb, 0xb0, 0x40, 0x3f, 0x0a,
- 0xa8, 0xe3, 0xb7, 0x5c, 0x47, 0x9f, 0x33, 0x36, 0x73, 0x3c, 0x72, 0xd7, 0xf8, 0x7e, 0x53, 0x9f,
- 0x33, 0xba, 0xb0, 0x2c, 0xdd, 0x48, 0xf9, 0xaa, 0xd8, 0x82, 0x0d, 0xb9, 0xd6, 0x70, 0xff, 0xe6,
- 0x5f, 0x61, 0x1d, 0xae, 0x4d, 0x96, 0xd3, 0x40, 0xd7, 0xd8, 0x2c, 0xe4, 0x4a, 0x18, 0xbd, 0x60,
- 0xfc, 0x04, 0x96, 0x32, 0xb8, 0xc3, 0xd7, 0xe1, 0xaa, 0xfa, 0xdc, 0x8e, 0xe2, 0xc3, 0x5e, 0x7c,
- 0xa4, 0xcf, 0xe5, 0x0b, 0xbc, 0xb3, 0x38, 0x66, 0x05, 0xb8, 0xe2, 0xd5, 0x82, 0x20, 0x3a, 0x3d,
- 0xe9, 0xc5, 0xdd, 0x71, 0x74, 0xa8, 0x17, 0x8c, 0xbb, 0xb0, 0x9c, 0x01, 0x46, 0x61, 0xaf, 0x66,
- 0xb9, 0x42, 0x20, 0xd8, 0xb4, 0xde, 0xea, 0xd8, 0x7a, 0x99, 0xad, 0xf5, 0x66, 0x6b, 0xb7, 0xa9,
- 0x83, 0xf1, 0x47, 0x8d, 0x1d, 0x49, 0x11, 0xc3, 0xd0, 0x6e, 0x98, 0x72, 0x30, 0xd8, 0x44, 0x70,
- 0x0c, 0x25, 0xea, 0xfb, 0xfc, 0x7e, 0x6f, 0x13, 0xd6, 0xc5, 0x43, 0x68, 0x3a, 0xf5, 0xb0, 0x69,
- 0x7a, 0xf5, 0x7d, 0xd3, 0x63, 0xb3, 0xf3, 0x50, 0x2f, 0xe0, 0x92, 0x53, 0x28, 0x61, 0xe0, 0x76,
- 0x6a, 0x4d, 0xbd, 0xc8, 0x66, 0x38, 0x43, 0x6f, 0xb7, 0x1c, 0xbd, 0x84, 0x0b, 0x78, 0x82, 0x1b,
- 0x9b, 0x65, 0xe5, 0x65, 0xa3, 0x07, 0x7a, 0x3e, 0x70, 0x62, 0xe2, 0xa2, 0xd5, 0xeb, 0x38, 0x0e,
- 0xdf, 0xa1, 0x2b, 0xb0, 0xe8, 0x06, 0x4d, 0xea, 0x09, 0x94, 0x2b, 0x84, 0xb5, 0xea, 0x38, 0x66,
- 0x27, 0x68, 0xba, 0x5e, 0xeb, 0x11, 0x6e, 0xd5, 0x75, 0xb8, 0xe6, 0x5b, 0x66, 0x6d, 0x2f, 0x74,
- 0xdc, 0x20, 0x6c, 0x39, 0x61, 0xad, 0x69, 0x3a, 0x0e, 0xb5, 0x74, 0x30, 0xfe, 0xae, 0xc1, 0x8d,
- 0x73, 0xae, 0x63, 0xc8, 0x1b, 0x70, 0xa7, 0x49, 0xcd, 0xba, 0x45, 0x7d, 0x3f, 0x64, 0x4d, 0x52,
- 0x27, 0x10, 0x77, 0x9e, 0x53, 0x97, 0xc3, 0x1d, 0xf8, 0xd6, 0xf9, 0xec, 0xa9, 0x60, 0xf9, 0x36,
- 0xbc, 0x7e, 0x3e, 0xab, 0x10, 0x34, 0x05, 0x62, 0xc0, 0xed, 0xf3, 0x39, 0x13, 0x01, 0x55, 0x34,
- 0x7e, 0xaf, 0xc1, 0xda, 0x74, 0x7d, 0x8c, 0xf5, 0xad, 0xe5, 0xf8, 0x81, 0x69, 0x59, 0x61, 0xdb,
- 0xf4, 0x4c, 0x3b, 0xa4, 0x8e, 0xe7, 0x5a, 0xd6, 0xb4, 0x8d, 0xf9, 0x3a, 0xdc, 0x9a, 0xcd, 0xea,
- 0xd7, 0xbc, 0x56, 0x9b, 0xad, 0xf0, 0x2a, 0x6c, 0xcd, 0xe6, 0xa2, 0xad, 0x1a, 0xd5, 0x0b, 0x3b,
- 0x1f, 0x7c, 0xf6, 0xaf, 0xad, 0xb9, 0xcf, 0x9e, 0x6f, 0x69, 0x9f, 0x3f, 0xdf, 0xd2, 0xfe, 0xf9,
- 0x7c, 0x4b, 0x7b, 0xf4, 0x9d, 0x4b, 0xe4, 0xb7, 0x7b, 0x5c, 0xc1, 0x4b, 0xfe, 0xef, 0xff, 0x37,
- 0x00, 0x00, 0xff, 0xff, 0x6f, 0xf4, 0xbe, 0xb2, 0xf1, 0x7f, 0x01, 0x00,
+ 0xaf, 0x24, 0xb1, 0xe3, 0x6b, 0xe8, 0x36, 0xc3, 0x0f, 0xb8, 0xce, 0x59, 0x71, 0xa0, 0xe8, 0x83,
+ 0x2b, 0x0f, 0xfd, 0x84, 0xd6, 0x24, 0xac, 0xc1, 0x54, 0xd2, 0x1a, 0x1c, 0xfa, 0x03, 0x10, 0x75,
+ 0xfe, 0x50, 0x0a, 0x2e, 0x1c, 0xd7, 0x66, 0xb2, 0x0d, 0xa7, 0xf1, 0xdd, 0xdb, 0x73, 0x82, 0x6e,
+ 0xd7, 0x1b, 0x56, 0x63, 0x9f, 0x8a, 0x55, 0x62, 0x24, 0x76, 0xbe, 0xdb, 0xad, 0xd5, 0x36, 0x94,
+ 0x7e, 0x77, 0xbb, 0x35, 0xcf, 0x91, 0xbf, 0x4b, 0x8c, 0x5c, 0xb4, 0xa1, 0x09, 0xcf, 0x0f, 0xa0,
+ 0x54, 0x3e, 0xab, 0x94, 0xfa, 0x59, 0x5d, 0x86, 0xfc, 0x2e, 0x6d, 0x32, 0x11, 0x8a, 0x36, 0xb1,
+ 0x69, 0x0f, 0x96, 0x78, 0xf6, 0x3d, 0x73, 0x3a, 0x80, 0xd7, 0x3c, 0xe7, 0xfe, 0x92, 0xa8, 0xa5,
+ 0x2d, 0x77, 0x48, 0x55, 0x44, 0x23, 0x57, 0x61, 0x2e, 0xe2, 0xab, 0x1f, 0x3a, 0x7f, 0x9a, 0xb3,
+ 0xac, 0x48, 0x8f, 0xec, 0xf2, 0x22, 0x4c, 0xca, 0x69, 0x70, 0x03, 0x17, 0x12, 0x73, 0x42, 0xc0,
+ 0xd8, 0x2a, 0x17, 0xd5, 0xfd, 0xdd, 0xb4, 0x14, 0x99, 0x96, 0x1d, 0xc7, 0xf7, 0x7c, 0xd7, 0xea,
+ 0x6a, 0xf7, 0x26, 0xd2, 0x86, 0xb3, 0x8e, 0xd5, 0xf3, 0xf7, 0x97, 0xea, 0xec, 0x5f, 0xc7, 0x95,
+ 0xfe, 0x9c, 0x0d, 0x69, 0x09, 0x37, 0xb1, 0x74, 0x4d, 0xdf, 0x3a, 0x8b, 0x0c, 0xbb, 0xa8, 0x22,
+ 0xb3, 0x13, 0x5e, 0xe1, 0xba, 0xfa, 0x9c, 0x79, 0x86, 0xf3, 0x8c, 0x61, 0x91, 0x55, 0xd0, 0x32,
+ 0xdb, 0x27, 0x5e, 0x9c, 0x94, 0x2c, 0xf4, 0x3a, 0xd7, 0x89, 0x1d, 0x25, 0x0d, 0xfe, 0x7b, 0x30,
+ 0x6e, 0x37, 0x45, 0xfc, 0x38, 0x71, 0x7d, 0xd2, 0x45, 0xf6, 0x4a, 0x93, 0x87, 0x93, 0x0b, 0x79,
+ 0xb0, 0xbb, 0x97, 0x2d, 0xa0, 0xcb, 0x53, 0xda, 0x0d, 0xd3, 0x58, 0x96, 0xa7, 0x73, 0x9c, 0x2c,
+ 0x96, 0xa4, 0xfc, 0x34, 0x8c, 0x7a, 0x4a, 0x40, 0x3b, 0x53, 0xfc, 0x32, 0xfe, 0x02, 0x5c, 0x1e,
+ 0x76, 0x8c, 0xc8, 0x1b, 0x40, 0xfa, 0x0c, 0xf8, 0xb8, 0x39, 0x6b, 0xc5, 0xc6, 0xed, 0x45, 0x50,
+ 0x23, 0x72, 0xd9, 0x72, 0xc2, 0x25, 0x6c, 0xcb, 0xb5, 0x8d, 0x77, 0x61, 0x5a, 0xbf, 0x52, 0x93,
+ 0xd7, 0x20, 0x1b, 0x70, 0x9d, 0x0e, 0x54, 0xbf, 0x2a, 0x12, 0xe3, 0x6d, 0x22, 0x92, 0xf1, 0x4f,
+ 0xd3, 0x30, 0x97, 0x70, 0xb1, 0x26, 0x1f, 0xc2, 0x9c, 0x5c, 0x20, 0x7c, 0xe3, 0xe1, 0x13, 0xc7,
+ 0x97, 0xc6, 0x95, 0xa4, 0xa5, 0x81, 0x68, 0x09, 0xd3, 0x37, 0x2b, 0x16, 0x45, 0x58, 0xfe, 0xe7,
+ 0x67, 0x39, 0x90, 0x0f, 0xe0, 0xb4, 0x48, 0x14, 0xab, 0xac, 0x8a, 0xba, 0x4b, 0x77, 0x85, 0xfc,
+ 0xf0, 0x62, 0x6c, 0xf4, 0xec, 0x86, 0xd2, 0x1c, 0x93, 0xee, 0xae, 0x3e, 0x67, 0xce, 0x7b, 0x09,
+ 0xf0, 0xe8, 0x4a, 0xfb, 0x77, 0x52, 0x60, 0x1c, 0x3f, 0x5e, 0x28, 0xf1, 0x46, 0x07, 0x9c, 0x49,
+ 0xbc, 0xca, 0xe8, 0x5d, 0x84, 0x29, 0x97, 0xee, 0xba, 0xd4, 0xdb, 0xaf, 0xab, 0x49, 0xf3, 0x27,
+ 0x05, 0x50, 0x0e, 0x8c, 0x74, 0x49, 0x1f, 0x42, 0x91, 0x9e, 0xfb, 0xce, 0x51, 0xe1, 0x39, 0xae,
+ 0x02, 0x15, 0x44, 0xc6, 0xad, 0x60, 0x03, 0x49, 0x9c, 0x87, 0x30, 0x63, 0x7f, 0x4a, 0xc9, 0xd8,
+ 0x7f, 0x27, 0x9b, 0x4b, 0xe7, 0x33, 0xa6, 0x70, 0x9c, 0xdf, 0xb5, 0x5b, 0xd4, 0xf8, 0xf5, 0x14,
+ 0x2c, 0xf6, 0x1f, 0x3c, 0xf2, 0xa1, 0xf2, 0x14, 0x94, 0xe1, 0x71, 0xc3, 0x8e, 0x19, 0x6f, 0x55,
+ 0x6b, 0x2e, 0x7c, 0xb9, 0xa3, 0x39, 0x52, 0x05, 0xcb, 0x27, 0xd1, 0x67, 0xbf, 0x25, 0x35, 0x49,
+ 0x4c, 0x06, 0xbb, 0x7f, 0x9d, 0x5c, 0x81, 0x31, 0xae, 0x3c, 0x92, 0x0d, 0x9d, 0xd1, 0x1a, 0x7a,
+ 0xff, 0xba, 0x29, 0xcb, 0x8d, 0x6f, 0xa7, 0x82, 0xeb, 0x73, 0xb4, 0xf9, 0xf7, 0xaf, 0x93, 0xcf,
+ 0x0c, 0xf7, 0xa8, 0x93, 0x93, 0x8f, 0x3a, 0xc1, 0x83, 0xce, 0x67, 0xb5, 0x07, 0x9d, 0x97, 0x06,
+ 0x8f, 0x93, 0x10, 0xd4, 0xa3, 0x59, 0xec, 0xfe, 0x79, 0x0a, 0xce, 0x0f, 0xa4, 0x20, 0xe7, 0x20,
+ 0x57, 0xac, 0x56, 0x36, 0xc3, 0x99, 0x65, 0x5f, 0x8b, 0x84, 0x90, 0xdb, 0x30, 0xbe, 0x6c, 0x79,
+ 0x76, 0x83, 0x2d, 0xe0, 0x44, 0xd1, 0x23, 0xc6, 0x36, 0x40, 0x5f, 0x7d, 0xce, 0x0c, 0x69, 0x49,
+ 0x1d, 0x66, 0xf1, 0x2b, 0x88, 0x65, 0x89, 0x8a, 0x1e, 0x3b, 0x31, 0x86, 0x31, 0x32, 0xb6, 0xc3,
+ 0xc4, 0x80, 0xd1, 0x8f, 0xef, 0x81, 0x94, 0x33, 0xfa, 0x37, 0xf0, 0x04, 0xe1, 0x17, 0x2e, 0x43,
+ 0xae, 0x2a, 0xaf, 0xd0, 0x4a, 0x92, 0x48, 0x79, 0x5d, 0x36, 0x83, 0x52, 0xe3, 0xaf, 0xa6, 0xe4,
+ 0xd9, 0x70, 0x7c, 0x47, 0x94, 0x08, 0xab, 0xcd, 0xc1, 0x11, 0x56, 0x9b, 0x1f, 0x33, 0xc2, 0xaa,
+ 0xf1, 0x4b, 0x22, 0x38, 0x52, 0xa5, 0x59, 0x8d, 0x84, 0xd7, 0x7f, 0xd2, 0x27, 0xea, 0x15, 0x6d,
+ 0x75, 0x5e, 0x54, 0x42, 0x35, 0xc7, 0xeb, 0xea, 0xff, 0x52, 0xad, 0x2c, 0xd5, 0x7f, 0x9a, 0x86,
+ 0x73, 0x83, 0xc8, 0x13, 0x33, 0x01, 0xa4, 0x4e, 0x96, 0x09, 0xe0, 0x0a, 0xe4, 0x38, 0x4c, 0xcf,
+ 0x68, 0x26, 0x48, 0xd9, 0x80, 0xcb, 0x62, 0x72, 0x11, 0x46, 0x8b, 0xa5, 0x5a, 0x18, 0x96, 0x16,
+ 0xdf, 0x54, 0xac, 0x86, 0x87, 0xda, 0x7a, 0x51, 0x44, 0xbe, 0x12, 0x8f, 0xc4, 0x2c, 0xe2, 0xd1,
+ 0x3e, 0xaf, 0x0c, 0x48, 0x2c, 0x6e, 0x19, 0xb6, 0x37, 0x8c, 0xb3, 0x25, 0x42, 0xd7, 0x98, 0xf1,
+ 0xa8, 0xce, 0x06, 0x8c, 0x56, 0x5d, 0xea, 0x51, 0x5f, 0x7d, 0xef, 0xe8, 0x22, 0xc4, 0x14, 0x25,
+ 0xe2, 0x35, 0xc2, 0x3a, 0xe4, 0x16, 0xe5, 0xa3, 0xaa, 0xc3, 0x0d, 0x3e, 0x5f, 0x30, 0xb0, 0xa9,
+ 0xa0, 0x18, 0xdf, 0x4c, 0xc1, 0x7c, 0x52, 0xb3, 0xc8, 0x39, 0xc8, 0x76, 0x12, 0x63, 0x48, 0x77,
+ 0xb8, 0x5d, 0xeb, 0x04, 0x66, 0x93, 0xda, 0x75, 0xdc, 0xb6, 0xe5, 0xab, 0x8f, 0x3c, 0x0a, 0xd8,
+ 0x04, 0xf6, 0xe3, 0x16, 0xfe, 0x4d, 0x0a, 0x72, 0xb3, 0xcd, 0xc4, 0xa2, 0x4e, 0xe3, 0x7f, 0x46,
+ 0x11, 0xa0, 0xd2, 0xac, 0x6e, 0x74, 0x79, 0x18, 0xac, 0x1b, 0x90, 0x65, 0xcd, 0x8a, 0x2c, 0x46,
+ 0xb6, 0x1c, 0x8a, 0xf7, 0xd6, 0x04, 0x12, 0x6f, 0x15, 0x93, 0x93, 0x4d, 0x44, 0x36, 0xb6, 0x61,
+ 0x5a, 0xc7, 0x20, 0x2b, 0x7a, 0xe0, 0x84, 0x30, 0xd1, 0xf5, 0xb2, 0xe3, 0x70, 0x43, 0x83, 0xe5,
+ 0xb3, 0xdf, 0x3d, 0x2a, 0x00, 0xfb, 0xc9, 0x69, 0x92, 0x02, 0x2b, 0x18, 0x3f, 0x95, 0x86, 0xf9,
+ 0xd0, 0x60, 0x59, 0x7e, 0x12, 0xcf, 0xac, 0xf5, 0x5c, 0x51, 0xb3, 0xee, 0x2a, 0xc4, 0x72, 0xc9,
+ 0xca, 0x0e, 0x0e, 0x30, 0x2a, 0xb9, 0x0d, 0x0b, 0xfd, 0xf0, 0xc9, 0x6b, 0xb1, 0x6c, 0x8f, 0xc2,
+ 0xb1, 0x2e, 0x48, 0x0b, 0xa9, 0x24, 0x7f, 0xfc, 0x47, 0x29, 0x58, 0x14, 0xcf, 0xe3, 0xf7, 0x2c,
+ 0xbb, 0x83, 0x19, 0xae, 0x1b, 0xf4, 0xe9, 0x58, 0x7f, 0xde, 0xd6, 0xb6, 0xa5, 0x97, 0x75, 0x2b,
+ 0x88, 0x58, 0x6d, 0xfd, 0x7b, 0x4b, 0xae, 0xa0, 0x0b, 0x65, 0x83, 0x2f, 0xde, 0x2c, 0xb7, 0xb6,
+ 0xef, 0x30, 0x80, 0x6a, 0x6d, 0x8f, 0x18, 0xc6, 0x5f, 0x82, 0x17, 0x06, 0x57, 0x40, 0xbe, 0x0c,
+ 0x53, 0xc5, 0x3d, 0xda, 0xf1, 0xb7, 0xba, 0x7b, 0xae, 0xd5, 0xa4, 0x52, 0x29, 0x20, 0x75, 0xf9,
+ 0x6a, 0x19, 0x77, 0x1b, 0x15, 0xd6, 0xdf, 0x0c, 0x5e, 0xef, 0x09, 0x22, 0xcd, 0x06, 0x45, 0xe5,
+ 0x66, 0x7c, 0x23, 0x05, 0x24, 0xce, 0x83, 0xdc, 0x84, 0xc9, 0xad, 0xcd, 0x52, 0xcd, 0xb7, 0x5c,
+ 0x7f, 0xd5, 0xe9, 0xb9, 0xc2, 0x1d, 0x93, 0x1b, 0x03, 0xfb, 0x0d, 0xb6, 0x33, 0xb8, 0x7e, 0x7d,
+ 0xdf, 0xe9, 0xb9, 0xa6, 0x86, 0x87, 0xb1, 0x4d, 0x29, 0x3d, 0x68, 0x5a, 0x87, 0x7a, 0x6c, 0x53,
+ 0x01, 0xd3, 0x62, 0x9b, 0x0a, 0x98, 0xf1, 0xb7, 0x53, 0xf0, 0xbc, 0xd4, 0x9b, 0x37, 0x13, 0xda,
+ 0x52, 0x42, 0x97, 0x17, 0x57, 0x86, 0xa3, 0x18, 0x24, 0x9b, 0xce, 0x4a, 0xaf, 0x30, 0x6c, 0x20,
+ 0x0a, 0xa9, 0x9c, 0x16, 0xd3, 0xfb, 0xfb, 0x4e, 0x77, 0x08, 0xb7, 0xb0, 0x7c, 0x30, 0xa3, 0xbe,
+ 0xd3, 0x45, 0x16, 0x48, 0x69, 0x50, 0x98, 0x57, 0x1b, 0x27, 0x5b, 0x4c, 0xee, 0xc1, 0x98, 0xf0,
+ 0xd7, 0x8d, 0xe8, 0x18, 0x06, 0xf4, 0x69, 0x79, 0x46, 0xfa, 0x9e, 0x89, 0x70, 0x08, 0xa6, 0xe4,
+ 0x61, 0xfc, 0x64, 0x0a, 0x26, 0x98, 0xf0, 0x80, 0x11, 0x82, 0x9e, 0x74, 0x49, 0xeb, 0x72, 0xa0,
+ 0x54, 0x51, 0x05, 0xec, 0x87, 0x3a, 0x5c, 0xdf, 0x84, 0x99, 0x08, 0x01, 0x31, 0xd0, 0xeb, 0xa0,
+ 0x65, 0xf3, 0x44, 0xe9, 0x52, 0xbf, 0xa3, 0xc1, 0x8c, 0x7f, 0x25, 0x05, 0xf3, 0x1b, 0x07, 0xbe,
+ 0x55, 0x69, 0x77, 0x1d, 0xd7, 0x37, 0x7b, 0x2d, 0xf9, 0xbd, 0x33, 0x81, 0x48, 0x3e, 0xc0, 0x70,
+ 0x8b, 0x68, 0x2e, 0x10, 0x09, 0x98, 0x19, 0x94, 0x92, 0x55, 0xc8, 0x89, 0xf3, 0xc5, 0x13, 0x51,
+ 0x0c, 0xe4, 0xfb, 0xa2, 0xce, 0x58, 0x20, 0xb1, 0x9e, 0xe0, 0x16, 0x26, 0x68, 0xcc, 0x80, 0xda,
+ 0xf8, 0x93, 0x14, 0x9c, 0xe9, 0x43, 0x43, 0xde, 0x85, 0x11, 0x34, 0xec, 0x12, 0xb3, 0x77, 0xae,
+ 0x4f, 0x15, 0x7e, 0x63, 0xff, 0xfe, 0x75, 0x7e, 0x10, 0xb5, 0xd9, 0x0f, 0x93, 0x53, 0x91, 0x0f,
+ 0x61, 0xbc, 0xd8, 0x6c, 0x8a, 0x7b, 0x49, 0x5a, 0xbb, 0x97, 0xf4, 0xa9, 0xf1, 0x6a, 0x80, 0xcf,
+ 0xef, 0x25, 0xdc, 0xc4, 0xa0, 0xd9, 0xac, 0x0b, 0xa3, 0xb5, 0x90, 0xdf, 0xe2, 0x3b, 0x30, 0xad,
+ 0x23, 0x9f, 0xe8, 0x5e, 0xf2, 0xed, 0x14, 0xe4, 0xf5, 0x36, 0x7c, 0x32, 0x5e, 0x73, 0x49, 0xd3,
+ 0x7c, 0xcc, 0xa2, 0xfa, 0x99, 0x34, 0x9c, 0x4a, 0x1c, 0x61, 0xf2, 0x06, 0x8c, 0x16, 0xbb, 0xdd,
+ 0x4a, 0x59, 0xac, 0x2a, 0x21, 0xf0, 0xa0, 0x56, 0x4d, 0xbb, 0xb6, 0x71, 0x24, 0x72, 0x03, 0x72,
+ 0xb8, 0x32, 0x19, 0x41, 0x3a, 0x8c, 0x27, 0xc0, 0xd5, 0xd8, 0x91, 0x78, 0x02, 0x12, 0x91, 0xdc,
+ 0x82, 0x69, 0xe1, 0x40, 0x63, 0xd2, 0x3d, 0xfa, 0x28, 0x08, 0x6c, 0x85, 0xb1, 0xb7, 0xa4, 0xbb,
+ 0x4d, 0xdd, 0xe5, 0x65, 0xaa, 0x0b, 0x89, 0x4e, 0x85, 0xd9, 0x47, 0x19, 0x4f, 0x95, 0x13, 0x0f,
+ 0x6a, 0xc0, 0xb3, 0x8f, 0x62, 0x23, 0xfa, 0xf0, 0x8a, 0x51, 0x06, 0xd3, 0x55, 0xf4, 0x3c, 0x7b,
+ 0xaf, 0xd3, 0xa6, 0x1d, 0xff, 0x93, 0x9b, 0xae, 0xb0, 0x8e, 0xa1, 0xa6, 0xeb, 0x5b, 0x59, 0xfe,
+ 0x31, 0x47, 0xc9, 0x8e, 0x49, 0xb0, 0x5d, 0x86, 0x31, 0xee, 0xba, 0x23, 0xbf, 0x8c, 0xf3, 0x89,
+ 0x4d, 0xe0, 0x38, 0xf7, 0xaf, 0x73, 0xf1, 0x85, 0x5b, 0x98, 0x79, 0xa6, 0x24, 0x25, 0xf7, 0x61,
+ 0xa2, 0xd4, 0xa2, 0x56, 0xa7, 0xd7, 0x65, 0x9b, 0xf4, 0x10, 0x1a, 0x8a, 0x05, 0xd1, 0x97, 0xc9,
+ 0x06, 0x27, 0xab, 0xfb, 0x76, 0x9b, 0xe2, 0x4e, 0xae, 0x32, 0x22, 0x9b, 0x81, 0xd1, 0x49, 0x16,
+ 0x95, 0x5f, 0x9f, 0x1a, 0x30, 0x3e, 0x51, 0x20, 0xd2, 0xe9, 0x16, 0x55, 0xc2, 0x2a, 0xa5, 0x0e,
+ 0xd3, 0x6b, 0x96, 0xe7, 0x6f, 0xba, 0x56, 0xc7, 0x43, 0xef, 0xfb, 0x21, 0x5c, 0x22, 0x65, 0x92,
+ 0xaf, 0x19, 0x74, 0x79, 0xf1, 0x03, 0x52, 0x6c, 0x73, 0x84, 0x1d, 0x93, 0x97, 0x6e, 0xd9, 0x1d,
+ 0xab, 0x65, 0x7f, 0x5d, 0xda, 0xe6, 0x71, 0x79, 0x69, 0x57, 0x02, 0xcd, 0xb0, 0xdc, 0xf8, 0x52,
+ 0x6c, 0xde, 0x78, 0x2b, 0x27, 0x60, 0x4c, 0x98, 0x63, 0x73, 0xf3, 0xe4, 0xea, 0xca, 0x7a, 0xb9,
+ 0xb2, 0x7e, 0x3b, 0x9f, 0x22, 0xd3, 0x00, 0x55, 0x73, 0xa3, 0xb4, 0x52, 0xab, 0xb1, 0xdf, 0x69,
+ 0xf6, 0x5b, 0xd8, 0x2e, 0xdf, 0xda, 0x5a, 0xcb, 0x67, 0x14, 0xf3, 0xe5, 0xac, 0xf1, 0x0f, 0x53,
+ 0x70, 0x3a, 0x79, 0x2a, 0xc9, 0x26, 0xa0, 0x01, 0xbb, 0xd0, 0x2b, 0xde, 0x1c, 0x38, 0xef, 0x89,
+ 0xe0, 0xa8, 0x21, 0xbc, 0xcf, 0x0d, 0xac, 0xd3, 0xf2, 0x95, 0x20, 0xcc, 0x74, 0x65, 0x37, 0x8d,
+ 0x12, 0x2c, 0xf4, 0xe3, 0xa1, 0x77, 0x75, 0x06, 0x26, 0x8a, 0xd5, 0xea, 0x5a, 0xa5, 0x54, 0xdc,
+ 0xac, 0x6c, 0xac, 0xe7, 0x53, 0x64, 0x1c, 0x46, 0x6e, 0x9b, 0x1b, 0x5b, 0xd5, 0x7c, 0xda, 0xf8,
+ 0x6b, 0x29, 0x98, 0xaa, 0x74, 0x7c, 0xba, 0xc7, 0x6d, 0x1d, 0x9e, 0xf4, 0xe3, 0xfb, 0x9c, 0xf6,
+ 0xf1, 0x2d, 0x04, 0xae, 0x1e, 0x41, 0x05, 0x43, 0x7d, 0x79, 0xff, 0x38, 0x05, 0xb3, 0x31, 0x1a,
+ 0x52, 0x83, 0xb1, 0xe2, 0x76, 0x6d, 0xa3, 0x52, 0x2e, 0x89, 0x96, 0x49, 0xa9, 0x5c, 0x40, 0xe3,
+ 0xb5, 0x70, 0x4b, 0xca, 0x87, 0x5e, 0xdd, 0xb1, 0x9b, 0x4a, 0xa8, 0xfe, 0xd5, 0xe7, 0x4c, 0xc9,
+ 0x09, 0x4f, 0xb2, 0xaf, 0xf7, 0x5c, 0x8a, 0x6c, 0xd3, 0x9a, 0x46, 0x33, 0x80, 0xc7, 0x19, 0xf3,
+ 0xd4, 0xdb, 0xac, 0x3c, 0xce, 0x3a, 0xe4, 0xb7, 0x3c, 0x05, 0x13, 0xe2, 0xd6, 0x82, 0x17, 0x82,
+ 0x1f, 0x4f, 0xc1, 0x42, 0xbf, 0xb6, 0xb2, 0x8b, 0x90, 0x6e, 0x56, 0x7d, 0x3a, 0x88, 0xdb, 0xa6,
+ 0xdb, 0x53, 0x4b, 0x34, 0xf2, 0x2e, 0x4c, 0xf0, 0x9c, 0x7f, 0xb5, 0x1b, 0x5b, 0x66, 0x45, 0x2c,
+ 0x10, 0x74, 0xbc, 0x14, 0xe9, 0xc9, 0xbd, 0x1b, 0x91, 0x5c, 0xd5, 0x2a, 0xbe, 0xf1, 0xa3, 0x29,
+ 0x58, 0xec, 0xdf, 0x45, 0x76, 0xc6, 0xfc, 0xbf, 0xd4, 0x5d, 0x5f, 0x6f, 0x1b, 0xc7, 0x11, 0xd7,
+ 0xf1, 0x5f, 0xa4, 0x91, 0x64, 0x9d, 0xd6, 0x8e, 0xac, 0xca, 0xb2, 0xe2, 0x12, 0xa9, 0x51, 0x5f,
+ 0x1b, 0xa7, 0x49, 0x1b, 0x24, 0x4a, 0x91, 0x06, 0x27, 0x72, 0x29, 0xd2, 0xba, 0x3f, 0xf4, 0xdd,
+ 0xd1, 0x8a, 0xdd, 0x3f, 0x07, 0x5a, 0x3a, 0x4b, 0x6c, 0xa9, 0x23, 0x23, 0x52, 0x71, 0xdd, 0xb7,
+ 0xbe, 0x14, 0x28, 0x8a, 0x02, 0x45, 0x5f, 0xfb, 0xd0, 0x97, 0xbc, 0xf4, 0x33, 0xf4, 0x0b, 0x04,
+ 0x28, 0x0a, 0xe4, 0x13, 0x14, 0xad, 0x81, 0x7e, 0x84, 0xbe, 0xe4, 0xa9, 0xd8, 0xd9, 0xdd, 0xbb,
+ 0xbd, 0x23, 0xa9, 0x48, 0x8e, 0xd1, 0x22, 0x6f, 0xe2, 0xec, 0xec, 0x6a, 0x6f, 0xff, 0xcc, 0xee,
+ 0xcc, 0xce, 0xfc, 0x26, 0x60, 0x37, 0xf3, 0xd4, 0x2f, 0x15, 0xcf, 0x18, 0xbc, 0xad, 0xe7, 0x1c,
+ 0x53, 0x13, 0x46, 0x56, 0x29, 0x97, 0x01, 0x5d, 0xcd, 0x7c, 0x91, 0xad, 0x24, 0x19, 0xab, 0x7f,
+ 0x2a, 0xc0, 0x1a, 0x5b, 0x3e, 0xfd, 0x68, 0x34, 0x32, 0xcf, 0xc6, 0xc7, 0x51, 0x3c, 0x16, 0x17,
+ 0x2a, 0xf2, 0x2e, 0x54, 0x8e, 0x2f, 0x67, 0x0b, 0xe4, 0xec, 0x84, 0x00, 0x8a, 0x64, 0xe9, 0x18,
+ 0xc0, 0xfe, 0x26, 0x37, 0x41, 0xc9, 0x34, 0x82, 0x12, 0x75, 0xc9, 0x5b, 0x18, 0x26, 0xf9, 0x46,
+ 0xde, 0x83, 0x32, 0xea, 0xfe, 0x42, 0x30, 0xca, 0x0b, 0xed, 0xf4, 0x9e, 0xa1, 0x65, 0xc0, 0xe3,
+ 0x15, 0xc8, 0x9b, 0x00, 0x29, 0x3a, 0x98, 0x90, 0x7c, 0x52, 0x89, 0x4e, 0x00, 0xc2, 0xbc, 0x85,
+ 0x93, 0x27, 0x5d, 0x01, 0xb9, 0x65, 0xc0, 0xaa, 0x1c, 0x92, 0xa1, 0x8c, 0x7f, 0xe6, 0x96, 0x08,
+ 0x6f, 0x85, 0x17, 0xb4, 0x86, 0x22, 0x06, 0xba, 0xfa, 0xef, 0x02, 0x2c, 0xec, 0xb3, 0x6b, 0x02,
+ 0x2a, 0xbf, 0xe7, 0x2b, 0xd3, 0x6f, 0xc3, 0xa2, 0x35, 0xe8, 0x0a, 0xcb, 0xfd, 0x48, 0x40, 0x30,
+ 0xa0, 0x73, 0x66, 0x7f, 0xd0, 0x95, 0x8f, 0x00, 0x23, 0x4f, 0x65, 0xfa, 0x12, 0xc7, 0xd2, 0x7b,
+ 0x50, 0xe1, 0x2f, 0xdc, 0xc2, 0x4c, 0x23, 0x2f, 0x8a, 0x49, 0x8f, 0xee, 0xf2, 0x62, 0xc5, 0xd8,
+ 0xcc, 0xdf, 0xc8, 0xd5, 0x5b, 0x8b, 0x40, 0x60, 0x50, 0x54, 0xfd, 0xf2, 0xc5, 0x54, 0x7d, 0x25,
+ 0xd2, 0xb4, 0x72, 0x91, 0x48, 0xd3, 0x8d, 0x6d, 0x58, 0x54, 0xfa, 0x73, 0xa9, 0x7b, 0xe3, 0xaf,
+ 0x0b, 0xb0, 0x8c, 0x5f, 0x95, 0xbc, 0x12, 0x7d, 0x3d, 0x0d, 0x17, 0xef, 0x67, 0x0c, 0x17, 0xeb,
+ 0xea, 0x7c, 0xf1, 0x2f, 0x3b, 0xc7, 0x62, 0x71, 0x0f, 0x56, 0x27, 0x18, 0xc9, 0x3b, 0x50, 0x66,
+ 0xdd, 0x97, 0x8a, 0x9e, 0x9e, 0x5f, 0x01, 0x29, 0x2a, 0x09, 0xfb, 0xf0, 0x91, 0xc7, 0xb9, 0xab,
+ 0xff, 0xd1, 0x60, 0x49, 0xc0, 0xc5, 0xc5, 0x4f, 0x06, 0x5f, 0x3a, 0x9c, 0xb7, 0xf3, 0xc3, 0xc9,
+ 0xc3, 0x24, 0xc4, 0x70, 0xfe, 0xaf, 0x07, 0x71, 0x3b, 0x33, 0x88, 0xd7, 0x93, 0x18, 0x65, 0xf9,
+ 0x39, 0xe7, 0x8c, 0xe1, 0x5f, 0x11, 0xb5, 0x23, 0xcb, 0x48, 0x7e, 0x06, 0x0b, 0x4e, 0xf4, 0x34,
+ 0xa3, 0x2f, 0xdd, 0x9e, 0xd1, 0xe8, 0xdd, 0x84, 0x91, 0xef, 0x29, 0x3c, 0x6a, 0xe2, 0xe8, 0x69,
+ 0x38, 0xf1, 0x88, 0x93, 0x36, 0xc9, 0x54, 0xa6, 0x6c, 0xb5, 0xcb, 0x2c, 0x7d, 0xe1, 0x8c, 0x87,
+ 0x91, 0x3f, 0x7f, 0x29, 0x02, 0xa4, 0x7e, 0x4c, 0x6c, 0x03, 0x46, 0x19, 0x50, 0x55, 0x61, 0x39,
+ 0x46, 0x92, 0xba, 0xc6, 0x05, 0x89, 0xdc, 0x16, 0x26, 0xd1, 0xc2, 0xec, 0x18, 0x72, 0x34, 0x8e,
+ 0xd6, 0x84, 0x9f, 0xd0, 0x61, 0xd4, 0xef, 0x72, 0x59, 0x5c, 0xc4, 0xbc, 0xfe, 0xd7, 0x52, 0xea,
+ 0x8c, 0xbc, 0x1f, 0xe8, 0x4d, 0x54, 0x67, 0x0c, 0x13, 0xbe, 0x81, 0xa5, 0x17, 0xf7, 0x0d, 0x2c,
+ 0xbf, 0x80, 0x6f, 0x60, 0xe5, 0x82, 0xbe, 0x81, 0x6d, 0x58, 0xe8, 0xc5, 0x9f, 0x44, 0xf1, 0x78,
+ 0x70, 0xfa, 0x0c, 0x3d, 0x87, 0x52, 0x43, 0x16, 0x1b, 0xea, 0x96, 0x2c, 0xe3, 0xf3, 0x8d, 0x07,
+ 0x66, 0xc2, 0xaf, 0x4e, 0x77, 0x42, 0x14, 0x2e, 0x0c, 0x5f, 0x14, 0x80, 0x4c, 0x36, 0x40, 0xde,
+ 0x87, 0x45, 0x2e, 0x82, 0xc3, 0xd3, 0xd1, 0xc7, 0xc2, 0xb1, 0x8c, 0x47, 0x58, 0x29, 0x64, 0x35,
+ 0xc2, 0x8a, 0x93, 0xbd, 0xd1, 0xc7, 0x7d, 0xf2, 0x53, 0xb8, 0x8a, 0x13, 0x30, 0x8c, 0x4e, 0x7b,
+ 0x83, 0xc3, 0x10, 0x31, 0x2e, 0xba, 0x7d, 0x81, 0xe2, 0xfd, 0x06, 0xa6, 0x9b, 0x98, 0x2c, 0x9e,
+ 0x31, 0x51, 0xe8, 0xbf, 0xd5, 0x46, 0xce, 0x36, 0x67, 0x24, 0x01, 0xe8, 0x6a, 0xfd, 0x27, 0x67,
+ 0xfd, 0xbe, 0x98, 0x7b, 0x03, 0x73, 0xf1, 0xe6, 0xca, 0x66, 0x34, 0x7c, 0x25, 0x6d, 0xb8, 0x71,
+ 0xd6, 0xef, 0x93, 0x77, 0x01, 0x06, 0x71, 0x78, 0xd2, 0x1b, 0x8d, 0xf8, 0x73, 0x42, 0xe2, 0x7b,
+ 0x99, 0x52, 0xd5, 0x61, 0x1c, 0xc4, 0x36, 0x27, 0x92, 0x1f, 0x00, 0x3a, 0x66, 0x63, 0xc4, 0x02,
+ 0xae, 0x80, 0xb2, 0xc0, 0xe5, 0x93, 0xc4, 0xec, 0x74, 0x1e, 0x45, 0x7e, 0xef, 0x57, 0xd2, 0x7f,
+ 0xe4, 0x11, 0xac, 0x8a, 0x88, 0xac, 0xfd, 0xde, 0xf8, 0x58, 0xdc, 0x7e, 0xbf, 0xca, 0xd5, 0x59,
+ 0xb9, 0xfe, 0xfe, 0xb6, 0x04, 0x60, 0xee, 0xfb, 0x32, 0x18, 0xf0, 0x0e, 0x94, 0xd9, 0x9d, 0x5e,
+ 0xda, 0x06, 0xd0, 0xb2, 0x8a, 0xed, 0xaa, 0x96, 0x55, 0xe4, 0x60, 0xfb, 0xd5, 0x8b, 0x8e, 0xd0,
+ 0x3c, 0x55, 0x48, 0x0d, 0x09, 0xa7, 0x9c, 0x94, 0xb9, 0x43, 0x72, 0x12, 0xb1, 0x00, 0xd2, 0xf0,
+ 0x3c, 0xa1, 0x65, 0xae, 0xa6, 0x71, 0x2e, 0xa2, 0x40, 0x00, 0xae, 0xa5, 0x21, 0x7e, 0xea, 0xf2,
+ 0x49, 0xd9, 0xc8, 0x1e, 0x94, 0x82, 0x6e, 0xe2, 0x59, 0x38, 0x23, 0x68, 0xf1, 0x96, 0x40, 0x59,
+ 0x4f, 0x03, 0x17, 0xaf, 0x8c, 0xbb, 0x99, 0x64, 0x14, 0xd8, 0x08, 0xa1, 0x50, 0x11, 0x19, 0x74,
+ 0x66, 0x44, 0xb0, 0x8b, 0x04, 0x3a, 0x02, 0xb7, 0x06, 0x89, 0xea, 0xad, 0x43, 0xe4, 0xca, 0x79,
+ 0x1b, 0x8a, 0xbe, 0x6f, 0x0b, 0x57, 0xfd, 0xe5, 0x54, 0x63, 0xf0, 0x7d, 0x5b, 0x66, 0x09, 0x3b,
+ 0x51, 0xaa, 0x31, 0x66, 0xf2, 0x43, 0x58, 0x54, 0x2e, 0xc4, 0x22, 0xc8, 0x05, 0xc7, 0xa0, 0x97,
+ 0x92, 0x33, 0xf7, 0xea, 0x94, 0x4c, 0x2c, 0xd0, 0xf7, 0xce, 0x1e, 0x47, 0xe6, 0x70, 0x88, 0x5e,
+ 0x71, 0x9f, 0x44, 0xa7, 0x1c, 0x0c, 0x6e, 0x3e, 0x85, 0x7c, 0x09, 0xbb, 0xc3, 0x61, 0x78, 0x28,
+ 0x4b, 0x55, 0xfb, 0x48, 0xbe, 0x66, 0x35, 0x52, 0x27, 0x88, 0x9d, 0x92, 0x59, 0x25, 0x01, 0x4f,
+ 0x49, 0xa9, 0x24, 0xa4, 0xaa, 0xc1, 0x9b, 0x53, 0x82, 0x2c, 0xf1, 0xe9, 0x49, 0x09, 0xb2, 0xcc,
+ 0x84, 0x56, 0x7e, 0x5a, 0x52, 0x82, 0xf7, 0xc5, 0xc8, 0x7d, 0x00, 0x70, 0x6f, 0xd0, 0x8b, 0xed,
+ 0x68, 0x7c, 0x3c, 0x38, 0x54, 0x62, 0x3d, 0x17, 0x7f, 0x3e, 0xe8, 0xc5, 0xe1, 0x09, 0x92, 0xbf,
+ 0xf8, 0xc7, 0x6b, 0x0a, 0x93, 0xa7, 0xfc, 0x4d, 0xbe, 0x0b, 0x0b, 0xec, 0x57, 0x90, 0x3a, 0x60,
+ 0x70, 0xa3, 0x1f, 0xd6, 0x16, 0xb9, 0x01, 0x13, 0x06, 0xb2, 0x8d, 0xf8, 0x8a, 0xbd, 0xe1, 0x58,
+ 0xb9, 0x8c, 0x4a, 0x30, 0xc5, 0xde, 0x70, 0x9c, 0xc7, 0x63, 0x51, 0x98, 0x49, 0x33, 0xe9, 0xba,
+ 0x44, 0xe8, 0x14, 0x30, 0x8e, 0x68, 0xd9, 0x12, 0x2b, 0x23, 0x94, 0x40, 0x10, 0x6a, 0x2e, 0x85,
+ 0x5c, 0x35, 0xec, 0x84, 0xdf, 0xac, 0xf3, 0xa7, 0x08, 0x71, 0x26, 0xf0, 0x4e, 0x8c, 0x8e, 0x0f,
+ 0xc3, 0x03, 0x24, 0x67, 0x3a, 0x91, 0x30, 0x93, 0x1d, 0x58, 0xe1, 0x11, 0x49, 0x09, 0xd2, 0xb7,
+ 0x38, 0x1f, 0x50, 0x12, 0xa5, 0x50, 0xe0, 0xea, 0xbf, 0xcf, 0x55, 0x20, 0x0d, 0x28, 0xa3, 0x42,
+ 0x26, 0xc2, 0x42, 0x6e, 0xa8, 0x7a, 0x68, 0x7e, 0xd5, 0xa3, 0x14, 0x40, 0x0d, 0x54, 0x95, 0x02,
+ 0xc8, 0x4a, 0x3e, 0x02, 0xa0, 0xf1, 0xe9, 0xa0, 0xdf, 0x47, 0xa8, 0x92, 0x79, 0x54, 0x67, 0x6e,
+ 0x66, 0x77, 0x0f, 0xb6, 0x92, 0x32, 0xc9, 0xac, 0xee, 0xec, 0x77, 0x98, 0x03, 0x34, 0x51, 0xda,
+ 0xaa, 0xb6, 0xa0, 0xc2, 0xb7, 0x0e, 0xc2, 0xfe, 0x08, 0x4c, 0x41, 0x05, 0x34, 0x86, 0xc3, 0xfe,
+ 0x08, 0xfa, 0x24, 0xec, 0x8f, 0x52, 0xa1, 0xba, 0x07, 0xd7, 0xa6, 0x7d, 0x58, 0x46, 0x85, 0xd4,
+ 0x2e, 0xaa, 0x42, 0xfe, 0xb9, 0x08, 0x4b, 0xd8, 0x9a, 0x94, 0x99, 0x26, 0x2c, 0xfb, 0x67, 0x8f,
+ 0x93, 0xf0, 0x39, 0x29, 0x3b, 0x79, 0x42, 0x7d, 0xb5, 0x40, 0x7d, 0x24, 0xca, 0xd4, 0x20, 0x14,
+ 0xae, 0x48, 0xb9, 0x2d, 0x72, 0x1d, 0x14, 0x52, 0xc4, 0x1d, 0x19, 0xd8, 0x3d, 0x99, 0xe9, 0x20,
+ 0x57, 0x29, 0x95, 0xde, 0xc5, 0xcb, 0x48, 0xef, 0xd2, 0x85, 0xa4, 0xf7, 0x8f, 0x61, 0x49, 0xfe,
+ 0x37, 0x94, 0xbb, 0xe5, 0xaf, 0x26, 0x77, 0x33, 0x8d, 0x11, 0x2b, 0x91, 0xbf, 0x95, 0x73, 0xe5,
+ 0x2f, 0xbe, 0xbc, 0xc9, 0x5d, 0x36, 0x91, 0xbc, 0x4c, 0xb4, 0x81, 0x50, 0xe0, 0xbb, 0xb5, 0xf6,
+ 0x0b, 0x9c, 0x69, 0xef, 0xc0, 0x82, 0x35, 0x90, 0x8f, 0x2e, 0x8a, 0xb5, 0xbb, 0x2f, 0x89, 0xea,
+ 0xe1, 0x9e, 0x70, 0x26, 0x67, 0x51, 0xf1, 0x65, 0x9c, 0x45, 0xdb, 0x00, 0x6d, 0x1e, 0xf4, 0x90,
+ 0x42, 0xf8, 0xe2, 0x96, 0x91, 0xd1, 0x11, 0x59, 0xa3, 0xbb, 0xc2, 0xcc, 0xa4, 0x93, 0x70, 0xcf,
+ 0x30, 0x0f, 0x0e, 0x06, 0x67, 0xf1, 0x38, 0x93, 0xf3, 0x42, 0x04, 0x4a, 0x85, 0x5d, 0x51, 0xa6,
+ 0x8a, 0x87, 0x5c, 0xb5, 0x97, 0x3b, 0x21, 0xe4, 0x7e, 0xe2, 0x57, 0x76, 0x6e, 0x0a, 0xc0, 0xea,
+ 0xc4, 0x08, 0xcd, 0xf4, 0x26, 0xab, 0xfe, 0x4d, 0x53, 0xe1, 0xce, 0x5e, 0x60, 0xaa, 0xdf, 0x03,
+ 0x48, 0x5e, 0xbd, 0xe5, 0x5c, 0x73, 0xfd, 0x27, 0xa1, 0xaa, 0xa3, 0x9c, 0xf2, 0x2a, 0x5f, 0x53,
+ 0x7c, 0x59, 0x5f, 0x13, 0xc0, 0xa2, 0xfb, 0x8b, 0x71, 0x37, 0x75, 0x93, 0x00, 0x3f, 0xb9, 0x77,
+ 0xa2, 0x64, 0x92, 0xa9, 0x0a, 0xd3, 0x5b, 0xeb, 0xcc, 0x54, 0x85, 0x49, 0xc5, 0xea, 0x7d, 0x58,
+ 0x51, 0x5d, 0xb8, 0x9f, 0xc5, 0x07, 0xe4, 0x47, 0x1c, 0xa7, 0x41, 0xcb, 0x68, 0x06, 0x0a, 0x13,
+ 0x93, 0xb8, 0xcf, 0xe2, 0x03, 0x7e, 0x5b, 0xe9, 0x3e, 0x55, 0xfb, 0x8a, 0x3a, 0xdb, 0xe7, 0x1a,
+ 0x90, 0x49, 0x76, 0x55, 0x9a, 0x68, 0xff, 0x87, 0xbb, 0x60, 0xee, 0x0e, 0x55, 0xba, 0xcc, 0x1d,
+ 0xca, 0xf8, 0x83, 0x06, 0x2b, 0x2d, 0xd3, 0x16, 0xd8, 0x64, 0xdc, 0x7a, 0xff, 0x4d, 0xb8, 0xd9,
+ 0x32, 0xed, 0xb0, 0xed, 0x5a, 0xad, 0xda, 0xc3, 0x70, 0x2a, 0xe4, 0xc8, 0x4d, 0xf8, 0xc6, 0x24,
+ 0x4b, 0x6a, 0xe5, 0xdf, 0x84, 0xf5, 0xc9, 0x62, 0x09, 0x4b, 0x32, 0xbd, 0xb2, 0x44, 0x30, 0x29,
+ 0x1a, 0x1f, 0xc2, 0x8a, 0x44, 0xeb, 0x08, 0x2c, 0x1f, 0x41, 0xbe, 0x56, 0x60, 0xf1, 0x01, 0xf5,
+ 0x5a, 0x8d, 0x87, 0x61, 0xa3, 0x63, 0x59, 0xfa, 0x1c, 0x59, 0x86, 0x05, 0x41, 0xa8, 0x99, 0xba,
+ 0x46, 0x96, 0x60, 0xbe, 0xe5, 0xf8, 0xb4, 0xd6, 0xf1, 0xa8, 0x5e, 0x30, 0x3e, 0x84, 0x2b, 0x69,
+ 0x3e, 0x77, 0x34, 0xd2, 0xbf, 0x02, 0x45, 0xcf, 0xdc, 0xd7, 0xe7, 0x08, 0x40, 0xa5, 0xbd, 0x57,
+ 0xf3, 0xdf, 0x7a, 0x4b, 0xd7, 0xc8, 0x22, 0xbc, 0xb2, 0x5b, 0x6b, 0x87, 0x7b, 0xb6, 0xaf, 0x17,
+ 0xd8, 0x0f, 0x73, 0xdf, 0xc7, 0x1f, 0x45, 0xe3, 0x7b, 0xb0, 0x8a, 0x77, 0x05, 0xab, 0x37, 0x1a,
+ 0x47, 0x71, 0x74, 0x8a, 0x7d, 0x58, 0x82, 0x79, 0x3f, 0x62, 0x9b, 0x7c, 0x1c, 0xf1, 0x0e, 0xd8,
+ 0x67, 0xfd, 0x71, 0x6f, 0xd8, 0x8f, 0x7e, 0xa9, 0x6b, 0xc6, 0x36, 0xac, 0x78, 0x83, 0xb3, 0x71,
+ 0x2f, 0x3e, 0xf2, 0xc7, 0x8c, 0xe3, 0xe8, 0x19, 0x79, 0x15, 0x56, 0x3b, 0x8e, 0x69, 0xef, 0xb4,
+ 0x76, 0x3b, 0x6e, 0xc7, 0x0f, 0x6d, 0x33, 0xa8, 0x35, 0xf9, 0x13, 0x81, 0xed, 0xfa, 0x41, 0xe8,
+ 0xd1, 0x1a, 0x75, 0x02, 0x5d, 0x33, 0x7e, 0xa7, 0xc1, 0x95, 0xce, 0x48, 0xb8, 0xb5, 0x76, 0x10,
+ 0x79, 0xe2, 0x16, 0x6c, 0x76, 0x7c, 0xea, 0x85, 0x81, 0xbb, 0x47, 0x9d, 0xb0, 0xe3, 0x9b, 0xbb,
+ 0x79, 0xbc, 0x9b, 0xd7, 0xe0, 0x86, 0xc2, 0xe1, 0xd1, 0x9a, 0xfb, 0x80, 0x7a, 0x61, 0xdb, 0xf4,
+ 0xfd, 0x7d, 0xd7, 0xab, 0xeb, 0x1a, 0xd9, 0x80, 0xb5, 0x29, 0x0c, 0x76, 0xc3, 0xd4, 0x0b, 0x13,
+ 0x65, 0x0e, 0xdd, 0x37, 0xad, 0x70, 0xc7, 0x0d, 0xf4, 0xa2, 0x61, 0xb3, 0x83, 0x0e, 0x21, 0x21,
+ 0x38, 0xa0, 0xe7, 0x3c, 0x94, 0x1c, 0xd7, 0xa1, 0xf9, 0x67, 0x9c, 0x25, 0x98, 0x37, 0xdb, 0x6d,
+ 0xcf, 0x7d, 0x80, 0x13, 0x0a, 0x50, 0xa9, 0x53, 0x87, 0xf5, 0xac, 0xc8, 0x4a, 0xda, 0x9e, 0x6b,
+ 0xbb, 0x01, 0xad, 0xeb, 0x25, 0xc3, 0x93, 0x1b, 0x46, 0x36, 0x7a, 0x30, 0xe0, 0x6f, 0x26, 0x75,
+ 0xda, 0x30, 0x3b, 0x56, 0x20, 0x06, 0xe4, 0x61, 0xe8, 0xd1, 0xfb, 0x1d, 0xea, 0x07, 0xbe, 0xae,
+ 0x11, 0x1d, 0x96, 0x1c, 0x4a, 0xeb, 0x7e, 0xe8, 0xd1, 0x07, 0x2d, 0xba, 0xaf, 0x17, 0x58, 0x9b,
+ 0xfc, 0x6f, 0xf6, 0x1f, 0x8c, 0x4f, 0x35, 0x20, 0x1c, 0x4e, 0x43, 0x02, 0x2f, 0xe2, 0xfc, 0x6c,
+ 0xc1, 0x46, 0x93, 0x0d, 0x2c, 0x7e, 0x9a, 0xed, 0xd6, 0xf3, 0x43, 0xb6, 0x06, 0x24, 0x57, 0xee,
+ 0x36, 0x1a, 0xba, 0x46, 0x6e, 0xc0, 0xd5, 0x1c, 0xbd, 0xee, 0xb9, 0x6d, 0xbd, 0xb0, 0x51, 0x98,
+ 0xd7, 0xc8, 0xf5, 0x89, 0xc2, 0x3d, 0x4a, 0xdb, 0x7a, 0x91, 0x4d, 0x51, 0xae, 0x40, 0x2e, 0x40,
+ 0x5e, 0xbd, 0x64, 0xfc, 0x46, 0x83, 0x35, 0xde, 0x4d, 0xb9, 0x9a, 0x93, 0xae, 0x6e, 0xc2, 0xba,
+ 0x40, 0xfe, 0x99, 0xd6, 0xd1, 0x6b, 0xa0, 0x67, 0x4a, 0x79, 0x37, 0x5f, 0x85, 0xd5, 0x0c, 0x15,
+ 0xfb, 0x51, 0x60, 0x7b, 0x35, 0x43, 0xde, 0xa1, 0x7e, 0x10, 0xd2, 0x46, 0xc3, 0xf5, 0x02, 0xde,
+ 0x91, 0xa2, 0x51, 0x85, 0xd5, 0x5a, 0x74, 0x3a, 0x66, 0x3a, 0x48, 0x3c, 0xea, 0x0d, 0x62, 0xec,
+ 0xc2, 0x32, 0x2c, 0xd0, 0x8f, 0x02, 0xea, 0xf8, 0x2d, 0xd7, 0xd1, 0xe7, 0x8c, 0xcd, 0x1c, 0x8f,
+ 0xdc, 0x35, 0xbe, 0xdf, 0xd4, 0xe7, 0x8c, 0x2e, 0x2c, 0x4b, 0x37, 0x52, 0xbe, 0x2a, 0xb6, 0x60,
+ 0x43, 0xae, 0x35, 0xdc, 0xbf, 0xf9, 0x4f, 0x58, 0x87, 0x6b, 0x93, 0xe5, 0x34, 0xd0, 0x35, 0x36,
+ 0x0b, 0xb9, 0x12, 0x46, 0x2f, 0x18, 0x3f, 0x81, 0xa5, 0x0c, 0x42, 0xf1, 0x75, 0xb8, 0xaa, 0xfe,
+ 0x6e, 0x47, 0xf1, 0x61, 0x2f, 0x3e, 0xd2, 0xe7, 0xf2, 0x05, 0xde, 0x59, 0x1c, 0xb3, 0x02, 0x5c,
+ 0xf1, 0x6a, 0x41, 0x10, 0x9d, 0x9e, 0xf4, 0xe2, 0xee, 0x38, 0x3a, 0xd4, 0x0b, 0xc6, 0x5d, 0x58,
+ 0xce, 0x40, 0xa8, 0xb0, 0x4f, 0xb3, 0x5c, 0x21, 0x10, 0x6c, 0x5a, 0x6f, 0x75, 0x6c, 0xbd, 0xcc,
+ 0xd6, 0x7a, 0xb3, 0xb5, 0xdb, 0xd4, 0xc1, 0xf8, 0xa3, 0xc6, 0xae, 0xa4, 0x88, 0x76, 0x68, 0x37,
+ 0x4c, 0x39, 0x18, 0x6c, 0x22, 0x38, 0xda, 0x12, 0xf5, 0x7d, 0xfe, 0xbe, 0xb7, 0x09, 0xeb, 0xe2,
+ 0x47, 0x68, 0x3a, 0xf5, 0xb0, 0x69, 0x7a, 0xf5, 0x7d, 0xd3, 0x63, 0xb3, 0xf3, 0x50, 0x2f, 0xe0,
+ 0x92, 0x53, 0x28, 0x61, 0xe0, 0x76, 0x6a, 0x4d, 0xbd, 0xc8, 0x66, 0x38, 0x43, 0x6f, 0xb7, 0x1c,
+ 0xbd, 0x84, 0x0b, 0x78, 0x82, 0x1b, 0x9b, 0x65, 0xe5, 0x65, 0xa3, 0x07, 0x7a, 0x3e, 0x70, 0x62,
+ 0xe2, 0xa1, 0xd5, 0xeb, 0x38, 0x0e, 0xdf, 0xa1, 0x2b, 0xb0, 0xe8, 0x06, 0x4d, 0xea, 0x09, 0x3c,
+ 0x2c, 0x04, 0xc0, 0xea, 0x38, 0x66, 0x27, 0x68, 0xba, 0x5e, 0xeb, 0x11, 0x6e, 0xd5, 0x75, 0xb8,
+ 0xe6, 0x5b, 0x66, 0x6d, 0x2f, 0x74, 0xdc, 0x20, 0x6c, 0x39, 0x61, 0xad, 0x69, 0x3a, 0x0e, 0xb5,
+ 0x74, 0x30, 0xfe, 0xae, 0xc1, 0x8d, 0x73, 0x9e, 0x63, 0xc8, 0x1b, 0x70, 0xa7, 0x49, 0xcd, 0xba,
+ 0x45, 0x7d, 0x3f, 0x64, 0x4d, 0x52, 0x27, 0x10, 0x6f, 0x9e, 0x53, 0x97, 0xc3, 0x1d, 0xf8, 0xd6,
+ 0xf9, 0xec, 0xa9, 0x60, 0xf9, 0x36, 0xbc, 0x7e, 0x3e, 0xab, 0x10, 0x34, 0x05, 0x62, 0xc0, 0xed,
+ 0xf3, 0x39, 0x13, 0x01, 0x55, 0x34, 0x7e, 0xaf, 0xc1, 0xda, 0x74, 0x7d, 0x8c, 0xf5, 0xad, 0xe5,
+ 0xf8, 0x81, 0x69, 0x59, 0x61, 0xdb, 0xf4, 0x4c, 0x3b, 0xa4, 0x8e, 0xe7, 0x5a, 0xd6, 0xb4, 0x8d,
+ 0xf9, 0x3a, 0xdc, 0x9a, 0xcd, 0xea, 0xd7, 0xbc, 0x56, 0x9b, 0xad, 0xf0, 0x2a, 0x6c, 0xcd, 0xe6,
+ 0xa2, 0xad, 0x1a, 0xd5, 0x0b, 0x3b, 0x1f, 0x7c, 0xf6, 0xaf, 0xad, 0xb9, 0xcf, 0x9e, 0x6f, 0x69,
+ 0x9f, 0x3f, 0xdf, 0xd2, 0xfe, 0xf9, 0x7c, 0x4b, 0x7b, 0xf4, 0x9d, 0x4b, 0x64, 0xc2, 0x7b, 0x5c,
+ 0xc1, 0x47, 0xfe, 0xef, 0xff, 0x37, 0x00, 0x00, 0xff, 0xff, 0x25, 0xee, 0x1a, 0x11, 0x1b, 0x80,
+ 0x01, 0x00,
}
func (this *PluginSpecV1) Equal(that interface{}) bool {
@@ -21527,6 +21530,9 @@ func (this *PluginEntraIDSyncSettings) Equal(that interface{}) bool {
return false
}
}
+ if this.SsoConnectorId != that1.SsoConnectorId {
+ return false
+ }
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
@@ -40292,6 +40298,13 @@ func (m *PluginEntraIDSyncSettings) MarshalToSizedBuffer(dAtA []byte) (int, erro
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
+ if len(m.SsoConnectorId) > 0 {
+ i -= len(m.SsoConnectorId)
+ copy(dAtA[i:], m.SsoConnectorId)
+ i = encodeVarintTypes(dAtA, i, uint64(len(m.SsoConnectorId)))
+ i--
+ dAtA[i] = 0x12
+ }
if len(m.DefaultOwners) > 0 {
for iNdEx := len(m.DefaultOwners) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.DefaultOwners[iNdEx])
@@ -52026,6 +52039,10 @@ func (m *PluginEntraIDSyncSettings) Size() (n int) {
n += 1 + l + sovTypes(uint64(l))
}
}
+ l = len(m.SsoConnectorId)
+ if l > 0 {
+ n += 1 + l + sovTypes(uint64(l))
+ }
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@@ -108336,6 +108353,38 @@ func (m *PluginEntraIDSyncSettings) Unmarshal(dAtA []byte) error {
}
m.DefaultOwners = append(m.DefaultOwners, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field SsoConnectorId", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowTypes
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthTypes
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthTypes
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.SsoConnectorId = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTypes(dAtA[iNdEx:])
diff --git a/lib/config/configuration.go b/lib/config/configuration.go
index 7ad60892d4eb7..f6043a31e3307 100644
--- a/lib/config/configuration.go
+++ b/lib/config/configuration.go
@@ -242,6 +242,10 @@ type CommandLineFlags struct {
// `teleport integration configure access-graph aws-iam` command
IntegrationConfAccessGraphAWSSyncArguments IntegrationConfAccessGraphAWSSync
+ // IntegrationConfAzureOIDCArguments contains the arguments of
+ // `teleport integration configure azure-oidc` command
+ IntegrationConfAzureOIDCArguments IntegrationConfAzureOIDC
+
// IntegrationConfSAMLIdPGCPWorkforceArguments contains the arguments of
// `teleport integration configure samlidp gcp-workforce` command
IntegrationConfSAMLIdPGCPWorkforceArguments samlidpconfig.GCPWorkforceAPIParams
@@ -263,6 +267,22 @@ type IntegrationConfAccessGraphAWSSync struct {
Role string
}
+// IntegrationConfAzureOIDC contains the arguments of
+// `teleport integration configure azure-oidc` command
+type IntegrationConfAzureOIDC struct {
+ // ProxyPublicAddr is the publicly-reachable URL of the Teleport Proxy.
+ // It is used as the OIDC issuer URL, as well as for SAML URIs.
+ ProxyPublicAddr string
+
+ // AuthConnectorName is the name of the SAML connector that will be created on Teleport side.
+ AuthConnectorName string
+
+ // AccessGraphEnabled is a flag indicating that access graph integration is requested.
+ // When this is true, the integration script will produce
+ // a cache file necessary for TAG synchronization.
+ AccessGraphEnabled bool
+}
+
// IntegrationConfDeployServiceIAM contains the arguments of
// `teleport integration configure deployservice-iam` command
type IntegrationConfDeployServiceIAM struct {
diff --git a/lib/integrations/azureoidc/accessgraph.go b/lib/integrations/azureoidc/accessgraph.go
new file mode 100644
index 0000000000000..dff023f4cc710
--- /dev/null
+++ b/lib/integrations/azureoidc/accessgraph.go
@@ -0,0 +1,167 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package azureoidc
+
+import (
+ "bytes"
+ "compress/gzip"
+ "context"
+ "encoding/json"
+ "errors"
+ "io"
+ "log/slog"
+ "os"
+ "path"
+
+ "github.com/gravitational/trace"
+ msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
+
+ "github.com/gravitational/teleport/api/types"
+)
+
+var errNonSSOApp = errors.New("app does not have SSO set up")
+
+// singleSignOnMode represents the possible values for `currentSingleSignOnMode` in `adSingleSignOn`
+type singleSignOnMode string
+
+const (
+ // singleSignOnModeNone indicates that the application does not have SSO set up.
+ singleSignOnModeNone singleSignOnMode = "none" //nolint:unused // this serves as documentation of a possible value.
+ // singleSignOnModeFederated indicates federated SSO such as SAML.
+ singleSignOnModeFederated singleSignOnMode = "federated"
+)
+
+// adSingleSignOn represents the response from https://main.iam.ad.ext.azure.com/api/ApplicationSso/{servicePrincipalID}/SingleSignOn
+type adSingleSignOn struct {
+ CurrentSingleSignOnMode singleSignOnMode `json:"currentSingleSignOnMode"`
+}
+
+// tagInfoCache is the format for the file produced by CreateTAGCacheFile.
+type tagInfoCache struct {
+ AppSsoSettingsCache []*types.PluginEntraIDAppSSOSettings `json:"app_sso_settings_cache"`
+}
+
+// getSingleSignOn uses Azure private API to get basic information about an enterprise applications single sign on mode.
+func getSingleSignOn(ctx context.Context, token string, servicePrincipalID string) (*adSingleSignOn, error) {
+ payload, err := privateAPIGet(ctx, token, path.Join("ApplicationSso", servicePrincipalID, "SingleSignOn"))
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ var result adSingleSignOn
+ if err := json.Unmarshal(payload, &result); err != nil {
+ return nil, trace.Wrap(err, "failed to deserialize SingleSignOn")
+ }
+
+ return &result, nil
+}
+
+// getFederatedSSOV2Compressed retrieves the FederatedSsoV2 payload for the given AppId
+// and returns it as gzipped bytes.
+func getFederatedSSOV2Compressed(ctx context.Context, graphClient *msgraphsdk.GraphServiceClient, appID string, token string) ([]byte, error) {
+ sp, err := graphClient.ServicePrincipalsWithAppId(&appID).Get(ctx, nil)
+ if err != nil {
+ return nil, trace.Wrap(err, "could not retrieve service principal")
+ }
+ spID := sp.GetId()
+ if spID == nil {
+ return nil, trace.BadParameter("service principal ID is nil")
+ }
+
+ sso, err := getSingleSignOn(ctx, token, *spID)
+ if err != nil {
+ return nil, trace.Wrap(err, "failed to get single sign on data for app_id %s", appID)
+ } else if sso.CurrentSingleSignOnMode != singleSignOnModeFederated {
+ return nil, trace.Wrap(errNonSSOApp)
+ }
+
+ federatedSSOV2, err := privateAPIGet(ctx, token, path.Join("ApplicationSso", *spID, "FederatedSsoV2"))
+ if err != nil {
+ return nil, trace.Wrap(err, "getting federated SSO v2 info failed", "error", err)
+ }
+
+ federatedSSOV2Compressed, err := gzipBytes(federatedSSOV2)
+ return federatedSSOV2Compressed, trace.Wrap(err)
+}
+
+// CreateTAGCacheFile populates a file containing the information necessary for Access Graph to analyze Azure SSO.
+func CreateTAGCacheFile(ctx context.Context) error {
+ graphClient, err := createGraphClient()
+ if err != nil {
+ return trace.Wrap(err)
+ }
+
+ // Get information about enterprise apps
+ appResp, err := graphClient.Applications().Get(ctx, nil)
+ if err != nil {
+ return trace.Wrap(err)
+ }
+
+ // Authorize to the private API
+ tenantID, err := getTenantID()
+ if err != nil {
+ return trace.Wrap(err)
+ }
+ token, err := getPrivateAPIToken(ctx, tenantID)
+ if err != nil {
+ return trace.Wrap(err)
+ }
+
+ cache := &tagInfoCache{}
+
+ for _, app := range appResp.GetValue() {
+ appID := app.GetAppId()
+ if appID == nil {
+ slog.WarnContext(ctx, "app ID is nil", "app", app)
+ continue
+ }
+ federatedSSOV2Compressed, err := getFederatedSSOV2Compressed(ctx, graphClient, *appID, token)
+ if errors.Is(err, errNonSSOApp) {
+ slog.DebugContext(ctx, "sso not set up for app, will skip it", "app_id", *appID)
+ continue
+ } else if err != nil {
+ slog.WarnContext(ctx, "failed to retrieve SSO info", "app_id", *appID, "error", err)
+ }
+ cache.AppSsoSettingsCache = append(cache.AppSsoSettingsCache, &types.PluginEntraIDAppSSOSettings{
+ AppId: *appID,
+ FederatedSsoV2: federatedSSOV2Compressed,
+ })
+ }
+
+ payload, err := json.Marshal(cache)
+ if err != nil {
+ return trace.Wrap(err)
+ }
+ return trace.Wrap(os.WriteFile("cache.json", payload, 0600), "failed to write the TAG cache file")
+}
+
+// gzipBytes compresses the given byte slice, returning the result as a new byte slice.
+func gzipBytes(src []byte) ([]byte, error) {
+ out := new(bytes.Buffer)
+ writer := gzip.NewWriter(out)
+
+ _, err := io.Copy(writer, bytes.NewReader(src))
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ err = writer.Close()
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ return out.Bytes(), nil
+}
diff --git a/lib/integrations/azureoidc/enterprise_app.go b/lib/integrations/azureoidc/enterprise_app.go
new file mode 100644
index 0000000000000..49ced6a385175
--- /dev/null
+++ b/lib/integrations/azureoidc/enterprise_app.go
@@ -0,0 +1,210 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package azureoidc
+
+import (
+ "context"
+ "log/slog"
+ "net/url"
+ "path"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/gravitational/trace"
+ msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
+ "github.com/microsoftgraph/msgraph-sdk-go/applicationtemplates"
+ "github.com/microsoftgraph/msgraph-sdk-go/models"
+ "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"
+
+ "github.com/gravitational/teleport/api/utils/retryutils"
+)
+
+// nonGalleryAppTemplateID is a constant for the special application template ID in Microsoft Graph,
+// equivalent to the "create your own application" option in Azure portal.
+// Only non-gallery apps ("Create your own application" option in the UI) are allowed to use SAML SSO,
+// hence we use this template.
+// Ref: https://learn.microsoft.com/en-us/graph/api/applicationtemplate-instantiate
+const nonGalleryAppTemplateID = "8adf8e6e-67b2-4cf2-a259-e3dc5476c621"
+
+// A list of Microsoft Graph permissions ("app roles") for directory sync as performed by the Entra ID plugin.
+// Ref: https://learn.microsoft.com/en-us/graph/permissions-reference
+var appRoles = []string{
+ // Application.Read.All
+ "9a5d68dd-52b0-4cc2-bd40-abcf44ac3a30",
+ // Directory.Read.All
+ "7ab1d382-f21e-4acd-a863-ba3e13f7da61",
+ // Policy.Read.All
+ "246dd0d5-5bd0-4def-940b-0421030a5b68",
+}
+
+// SetupEnterpriseApp sets up an Enterprise Application in the Entra ID directory.
+// The enterprise application:
+// - Provides Teleport with OIDC authentication to Azure
+// - Is given the permissions to access certain Microsoft Graph API endpoints for this tenant.
+// - Provides SSO to the Teleport cluster via SAML.
+func SetupEnterpriseApp(ctx context.Context, proxyPublicAddr string, authConnectorName string) (string, string, error) {
+ var appID, tenantID string
+
+ tenantID, err := getTenantID()
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err)
+ }
+
+ graphClient, err := createGraphClient()
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err)
+ }
+
+ proxyURL, err := url.Parse(proxyPublicAddr)
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err, "could not parse URL of the Proxy Service")
+ }
+
+ displayName := "Teleport" + " " + proxyURL.Hostname()
+
+ instantiateRequest := applicationtemplates.NewItemInstantiatePostRequestBody()
+ instantiateRequest.SetDisplayName(&displayName)
+ appAndSP, err := graphClient.ApplicationTemplates().
+ ByApplicationTemplateId(nonGalleryAppTemplateID).
+ Instantiate().
+ Post(ctx, instantiateRequest, nil)
+
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to instantiate application template")
+ }
+
+ app := appAndSP.GetApplication()
+ sp := appAndSP.GetServicePrincipal()
+ appID = *app.GetAppId()
+ spID := *sp.GetId()
+
+ msGraphResourceID, err := getMSGraphResourceID(ctx, graphClient)
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to get MS Graph API resource ID")
+ }
+
+ msGraphResourceUUID := uuid.MustParse(msGraphResourceID)
+
+ r, err := retry()
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err)
+ }
+
+ const maxRetries = 10
+ for _, appRoleID := range appRoles {
+ r.Reset()
+ var err error
+
+ assignment := models.NewAppRoleAssignment()
+ spUUID := uuid.MustParse(spID)
+ assignment.SetPrincipalId(&spUUID)
+ assignment.SetResourceId(&msGraphResourceUUID)
+ appRoleUUID := uuid.MustParse(appRoleID)
+ assignment.SetAppRoleId(&appRoleUUID)
+
+ // There are some eventual consistency shenanigans instantiating enteprise applications,
+ // where assigning app roles may temporarily return "not found" for the newly-created App ID.
+ // Retry a few times to remediate.
+ for i := 0; i < maxRetries; i++ {
+ slog.DebugContext(ctx, "assign app role", "role_id", appRoleID, "attempt", i)
+ _, err = graphClient.ServicePrincipals().
+ ByServicePrincipalId(spID).
+ AppRoleAssignments().
+ Post(ctx, assignment, nil)
+ if err != nil {
+ r.Inc()
+ <-r.After()
+ } else {
+ break
+ }
+ }
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to assign app role %s", appRoleID)
+ }
+ }
+
+ if err := createFederatedAuthCredential(ctx, graphClient, *app.GetId(), proxyPublicAddr); err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to create an OIDC federated auth credential")
+ }
+
+ acsURL, err := url.Parse(proxyPublicAddr)
+ if err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to parse proxy public address")
+ }
+ acsURL.Path = path.Join("/v1/webapi/saml/acs", authConnectorName)
+ if err := setupSSO(ctx, graphClient, *app.GetId(), spID, acsURL.String()); err != nil {
+ return appID, tenantID, trace.Wrap(err, "failed to set up SSO for the enterprise app")
+ }
+
+ return appID, tenantID, nil
+}
+
+// createFederatedAuthCredential creates a new federated (OIDC) auth credential for the given Entra application.
+func createFederatedAuthCredential(ctx context.Context, graphClient *msgraphsdk.GraphServiceClient, appObjectID string, proxyPublicAddr string) error {
+ credential := models.NewFederatedIdentityCredential()
+ name := "teleport-oidc"
+ audiences := []string{azureDefaultJWTAudience}
+ subject := azureSubject
+ credential.SetName(&name)
+ credential.SetIssuer(&proxyPublicAddr)
+ credential.SetAudiences(audiences)
+ credential.SetSubject(&subject)
+
+ // ByApplicationID here means the object ID,
+ // i.e. app.GetId(), not app.GetAppId().
+ _, err := graphClient.Applications().ByApplicationId(appObjectID).
+ FederatedIdentityCredentials().Post(ctx, credential, nil)
+
+ return trace.Wrap(err)
+
+}
+
+// getMSGraphResourceID gets the resource ID for the Microsoft Graph app in the Entra directory.
+func getMSGraphResourceID(ctx context.Context, graphClient *msgraphsdk.GraphServiceClient) (string, error) {
+ requestFilter := "displayName eq 'Microsoft Graph'"
+
+ requestParameters := &serviceprincipals.ServicePrincipalsRequestBuilderGetQueryParameters{
+ Filter: &requestFilter,
+ }
+ configuration := &serviceprincipals.ServicePrincipalsRequestBuilderGetRequestConfiguration{
+ QueryParameters: requestParameters,
+ }
+ spResponse, err := graphClient.ServicePrincipals().Get(ctx, configuration)
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ spList := spResponse.GetValue()
+ switch len(spList) {
+ case 0:
+ return "", trace.NotFound("Microsoft Graph app not found in the tenant")
+ case 1:
+ return *spList[0].GetId(), nil
+ default:
+ return "", trace.BadParameter("Multiple service principals found for Microsoft Graph. This is not expected.")
+ }
+
+}
+
+func retry() (*retryutils.RetryV2, error) {
+ r, err := retryutils.NewRetryV2(retryutils.RetryV2Config{
+ First: time.Second,
+ Max: 10 * time.Second,
+ Driver: retryutils.NewExponentialDriver(time.Second),
+ })
+ return r, trace.Wrap(err)
+}
diff --git a/lib/integrations/azureoidc/private.go b/lib/integrations/azureoidc/private.go
new file mode 100644
index 0000000000000..0ffa09c1f075f
--- /dev/null
+++ b/lib/integrations/azureoidc/private.go
@@ -0,0 +1,179 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package azureoidc
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "log/slog"
+ "net/http"
+ "net/url"
+ "os"
+ "os/user"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/uuid"
+ "github.com/gravitational/trace"
+
+ "github.com/gravitational/teleport/lib/defaults"
+)
+
+type msalTokenCache struct {
+ RefreshToken map[string]msalToken `json:"RefreshToken"`
+}
+
+type msalToken struct {
+ ClientID string `json:"client_id"`
+ Secret string `json:"secret"`
+}
+
+type exchangeResponse struct {
+ AccessToken string `json:"access_token"`
+}
+
+// getRefreshTokens returns all current refresh tokens from the Azure CLI token cache.
+func getRefreshTokens() ([]msalToken, error) {
+ usr, err := user.Current()
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ f, err := os.Open(filepath.Join(usr.HomeDir, ".azure/msal_token_cache.json"))
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ var tokenCache msalTokenCache
+ if err := json.NewDecoder(f).Decode(&tokenCache); err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ var results []msalToken
+ for _, tok := range tokenCache.RefreshToken {
+ results = append(results, tok)
+ }
+ if len(results) == 0 {
+ return nil, trace.NotFound("no refresh tokens found in MSAL token cache")
+ }
+ return results, nil
+}
+
+// exchangeToken takes az CLI token and exchanges it for one suitable for the private API
+func exchangeToken(ctx context.Context, tenantID string, token msalToken) (string, error) {
+ params := url.Values{
+ "client_id": {token.ClientID},
+ "grant_type": {"refresh_token"},
+ "refresh_token": {token.Secret},
+ "scope": {"74658136-14ec-4630-ad9b-26e160ff0fc6/.default openid profile offline_access"},
+ }
+
+ uri := url.URL{
+ Host: "login.microsoftonline.com",
+ Path: path.Join(tenantID, "oauth2/v2.0/token"),
+ Scheme: "https",
+ }
+
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri.String(), strings.NewReader(params.Encode()))
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ client, err := defaults.HTTPClient()
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+ defer resp.Body.Close()
+ payload, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+ if resp.StatusCode != http.StatusOK {
+ return "", trace.Errorf("failed to exchange token: %s", string(payload))
+ }
+
+ var response exchangeResponse
+ err = json.Unmarshal(payload, &response)
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ if response.AccessToken == "" {
+ return "", trace.NotFound("expected non-empty AccessToken in the response")
+ }
+
+ return response.AccessToken, nil
+}
+
+// getPrivateAPIToken uses the azure CLI token cache to exchange a refresh token
+// for an access token authenticated to the "private" Azure API.
+func getPrivateAPIToken(ctx context.Context, tenantID string) (string, error) {
+ tokens, err := getRefreshTokens()
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+ for _, token := range tokens {
+ slog.DebugContext(ctx, "trying token", "client_id", token.ClientID)
+ token, err := exchangeToken(ctx, tenantID, token)
+ if err != nil {
+ slog.DebugContext(ctx, "error exchanging token", "err", err)
+ } else {
+ return token, nil
+ }
+ }
+ return "", trace.Errorf("no viable token")
+}
+
+// privateAPIGet invokes GET on the given endpoint of the "private" main.iam.ad.ext.azure.com azure API.
+// On status code 200 OK, it returns the payload received.
+// On any other status code, or protocol errors, it returns an error.
+func privateAPIGet(ctx context.Context, accessToken string, endpoint string) ([]byte, error) {
+ uri := url.URL{
+ Scheme: "https",
+ Host: "main.iam.ad.ext.azure.com",
+ Path: path.Join("api", endpoint),
+ }
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
+ req.Header.Add("x-ms-client-request-id", uuid.NewString())
+
+ client, err := defaults.HTTPClient()
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+ defer resp.Body.Close()
+ payload, err := io.ReadAll(resp.Body)
+ if resp.StatusCode != http.StatusOK {
+ return nil, trace.Errorf("request to %s failed: %s", endpoint, string(payload))
+ }
+ return payload, trace.Wrap(err)
+}
diff --git a/lib/integrations/azureoidc/provision.go b/lib/integrations/azureoidc/provision.go
new file mode 100644
index 0000000000000..60010faa9461a
--- /dev/null
+++ b/lib/integrations/azureoidc/provision.go
@@ -0,0 +1,100 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package azureoidc
+
+import (
+ "bytes"
+ "encoding/json"
+ "os"
+ "os/user"
+ "path/filepath"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
+ "github.com/gravitational/trace"
+ auth "github.com/microsoft/kiota-authentication-azure-go"
+ msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
+)
+
+// createGraphClient creates a new graph client from ambient credentials (Azure CLI credentials cache).
+func createGraphClient() (*msgraphsdk.GraphServiceClient, error) {
+ credential, err := azidentity.NewDefaultAzureCredential(nil)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ // Create an auth provider using the credential
+ authProvider, err := auth.NewAzureIdentityAuthenticationProviderWithScopes(credential, []string{
+ "https://graph.microsoft.com/.default",
+ })
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ // Create a request adapter using the auth provider
+ adapter, err := msgraphsdk.NewGraphRequestAdapter(authProvider)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ // Create a Graph client using request adapter
+ return msgraphsdk.NewGraphServiceClient(adapter), nil
+}
+
+func getAzureDir() (string, error) {
+ usr, err := user.Current()
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+ return filepath.Join(usr.HomeDir, ".azure"), nil
+}
+
+type azureCLIProfile struct {
+ Subscriptions []azureCLISubscription `json:"subscriptions"`
+}
+
+type azureCLISubscription struct {
+ TenantID string `json:"tenantID"`
+}
+
+// getTenantID infers the Azure tenant ID from the Azure CLI profiles.
+func getTenantID() (string, error) {
+ azureDir, err := getAzureDir()
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ payload, err := os.ReadFile(filepath.Join(azureDir, "azureProfile.json"))
+ if err != nil {
+ return "", trace.Wrap(err)
+ }
+
+ // Remove UTF-8 BOM
+ payload = bytes.TrimPrefix(payload, []byte("\xef\xbb\xbf"))
+
+ var profile azureCLIProfile
+ if err := json.Unmarshal(payload, &profile); err != nil {
+ return "", trace.Wrap(err)
+ }
+ if len(profile.Subscriptions) == 0 {
+ return "", trace.BadParameter("subscription not found")
+ }
+
+ // Users are expected to run this in the Azure Cloud Shell,
+ // where they are by default authenticated to only one subscription.
+ return profile.Subscriptions[0].TenantID, nil
+
+}
diff --git a/lib/integrations/azureoidc/provision_sso.go b/lib/integrations/azureoidc/provision_sso.go
new file mode 100644
index 0000000000000..f552de976c7c5
--- /dev/null
+++ b/lib/integrations/azureoidc/provision_sso.go
@@ -0,0 +1,91 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package azureoidc
+
+import (
+ "context"
+
+ "github.com/gravitational/trace"
+ msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
+ "github.com/microsoftgraph/msgraph-sdk-go/models"
+ "github.com/microsoftgraph/msgraph-sdk-go/serviceprincipals"
+)
+
+// setupSSO sets up SAML based SSO to Teleport for the given application (service principal).
+func setupSSO(ctx context.Context, graphClient *msgraphsdk.GraphServiceClient, appObjectID string, spID string, acsURL string) error {
+ spPatch := models.NewServicePrincipal()
+ // Set service principal to prefer SAML sign on
+ preferredSingleSignOnMode := "saml"
+ spPatch.SetPreferredSingleSignOnMode(&preferredSingleSignOnMode)
+ // Do not require explicit assignment of the app to use SSO.
+ // This is per our manual set-up recommendations, see https://goteleport.com/docs/access-controls/sso/azuread/ .
+ appRoleAssignmentRequired := false
+ spPatch.SetAppRoleAssignmentRequired(&appRoleAssignmentRequired)
+
+ _, err := graphClient.ServicePrincipals().
+ ByServicePrincipalId(spID).
+ Patch(ctx, spPatch, nil)
+
+ if err != nil {
+ return trace.Wrap(err, "failed to enable SSO for service principal")
+ }
+
+ // Add SAML urls
+ app := models.NewApplication()
+ app.SetIdentifierUris([]string{acsURL})
+ webApp := models.NewWebApplication()
+ webApp.SetRedirectUris([]string{acsURL})
+ app.SetWeb(webApp)
+
+ _, err = graphClient.Applications().
+ ByApplicationId(appObjectID).
+ Patch(ctx, app, nil)
+
+ if err != nil {
+ return trace.Wrap(err, "failed to set SAML URIs")
+ }
+
+ // Add a SAML signing certificate
+ certRequest := serviceprincipals.NewItemAddTokenSigningCertificatePostRequestBody()
+ // Display name is required to start with `CN=`.
+ // Ref: https://learn.microsoft.com/en-us/graph/api/serviceprincipal-addtokensigningcertificate
+ displayName := "CN=azure-sso"
+ certRequest.SetDisplayName(&displayName)
+
+ cert, err := graphClient.ServicePrincipals().
+ ByServicePrincipalId(spID).
+ AddTokenSigningCertificate().
+ Post(ctx, certRequest, nil)
+
+ if err != nil {
+ trace.Wrap(err, "failed to create a signing certificate")
+ }
+
+ // Set the preferred SAML signing key
+ spPatch = models.NewServicePrincipal()
+ spPatch.SetPreferredTokenSigningKeyThumbprint(cert.GetThumbprint())
+
+ _, err = graphClient.ServicePrincipals().
+ ByServicePrincipalId(spID).
+ Patch(ctx, spPatch, nil)
+
+ if err != nil {
+ return trace.Wrap(err, "failed to set SAML signing key")
+ }
+
+ return nil
+}
diff --git a/lib/integrations/azureoidc/token_generator.go b/lib/integrations/azureoidc/token_generator.go
index e31cf2e14f5da..c938ceb6debf4 100644
--- a/lib/integrations/azureoidc/token_generator.go
+++ b/lib/integrations/azureoidc/token_generator.go
@@ -34,6 +34,9 @@ import (
// when setting up an enterprise application.
const azureDefaultJWTAudience = "api://AzureADTokenExchange"
+// azureSubject is the subject of our choosing for the OIDC credential.
+const azureSubject = "teleport-azure"
+
// KeyStoreManager defines methods to get signers using the server's keystore.
type KeyStoreManager interface {
// GetJWTSigner selects a usable JWT keypair from the given keySet and returns a [crypto.Signer].
@@ -84,7 +87,7 @@ func GenerateEntraOIDCToken(ctx context.Context, cache Cache, manager KeyStoreMa
token, err := privateKey.SignEntraOIDC(jwt.SignParams{
Audience: azureDefaultJWTAudience,
- Subject: "teleport-azure", // TODO(justinas): consider moving this to a constant or a field in the integration settings
+ Subject: azureSubject,
Issuer: issuer,
Expires: clock.Now().Add(time.Hour),
})
diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go
index 7d4667f80aaf1..f597c7a388888 100644
--- a/lib/web/apiserver.go
+++ b/lib/web/apiserver.go
@@ -939,7 +939,10 @@ func (h *Handler) bindDefaultEndpoints() {
// SAML IDP integration endpoints
h.GET("/webapi/scripts/integrations/configure/gcp-workforce-saml.sh", h.WithLimiter(h.gcpWorkforceConfigScript))
- // AWS OIDC Integration specific endpoints:
+ // Azure OIDC integration endpoints
+ h.GET("/webapi/scripts/integrations/configure/azureoidc.sh", h.WithLimiter(h.azureOIDCConfigure))
+
+ // OIDC Integration specific endpoints:
// Unauthenticated access to OpenID Configuration - used for AWS OIDC IdP integration
h.GET("/.well-known/openid-configuration", h.WithLimiter(h.openidConfiguration))
h.GET(OIDCJWKWURI, h.WithLimiter(h.jwksOIDC))
diff --git a/lib/web/integrations_azureoidc.go b/lib/web/integrations_azureoidc.go
new file mode 100644
index 0000000000000..a83179fc56d54
--- /dev/null
+++ b/lib/web/integrations_azureoidc.go
@@ -0,0 +1,91 @@
+// Teleport
+// Copyright (C) 2024 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package web
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/google/safetext/shsprintf"
+ "github.com/gravitational/trace"
+ "github.com/julienschmidt/httprouter"
+
+ "github.com/gravitational/teleport/lib/httplib"
+ "github.com/gravitational/teleport/lib/utils/oidc"
+ "github.com/gravitational/teleport/lib/web/scripts/oneoff"
+)
+
+// azureOIDCConfigureIdP returns a script that configures Azure OIDC Integration
+// by creating an Enterprise Application in the Azure account
+// with Teleport OIDC as a trusted credential issuer.
+func (h *Handler) azureOIDCConfigure(w http.ResponseWriter, r *http.Request, p httprouter.Params) (any, error) {
+ ctx := r.Context()
+ queryParams := r.URL.Query()
+
+ oidcIssuer, err := oidc.IssuerFromPublicAddress(h.cfg.PublicProxyAddr)
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ authConnectorName := queryParams.Get("authConnectorName")
+ if authConnectorName == "" {
+ return nil, trace.BadParameter("authConnectorName must be specified")
+ }
+ // Ensure the auth connector name is valid
+ const withSecrets = false
+ _, err = h.GetProxyClient().GetSAMLConnector(ctx, authConnectorName, withSecrets)
+ // NotFound error is ignored to prevent disclosure of whether the integration exists in a public/no-auth endpoint.
+ if err != nil && !trace.IsNotFound(err) {
+ return nil, trace.Wrap(err)
+ }
+
+ integrationName := queryParams.Get("integrationName")
+ if len(integrationName) == 0 {
+ return nil, trace.BadParameter("integrationName must be specified")
+ }
+ // Ensure the integration name is valid.
+ _, err = h.GetProxyClient().GetIntegration(ctx, integrationName)
+ // NotFound error is ignored to prevent disclosure of whether the integration exists in a public/no-auth endpoint.
+ if err != nil && !trace.IsNotFound(err) {
+ return nil, trace.Wrap(err)
+ }
+
+ // The script must execute the following command:
+ argsList := []string{
+ "integration", "configure", "azure-oidc",
+ fmt.Sprintf("--proxy-public-addr=%s", shsprintf.EscapeDefaultContext(oidcIssuer)),
+ fmt.Sprintf("--auth-connector-name=%s", shsprintf.EscapeDefaultContext(authConnectorName)),
+ }
+
+ if tagParam := queryParams.Get("accessGraph"); tagParam != "" {
+ argsList = append(argsList, "--access-graph")
+ }
+
+ script, err := oneoff.BuildScript(oneoff.OneOffScriptParams{
+ TeleportArgs: strings.Join(argsList, " "),
+ SuccessMessage: "Success! You can now go back to the browser to use the integration with Azure.",
+ })
+ if err != nil {
+ return nil, trace.Wrap(err)
+ }
+
+ httplib.SetScriptHeaders(w.Header())
+ _, err = fmt.Fprint(w, script)
+
+ return nil, trace.Wrap(err)
+}
diff --git a/lib/web/integrations_azureoidc_test.go b/lib/web/integrations_azureoidc_test.go
new file mode 100644
index 0000000000000..a81106c0084d4
--- /dev/null
+++ b/lib/web/integrations_azureoidc_test.go
@@ -0,0 +1,129 @@
+/*
+ * Teleport
+ * Copyright (C) 2023 Gravitational, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package web
+
+import (
+ "context"
+ "fmt"
+ "net/url"
+ "testing"
+
+ "github.com/gravitational/trace"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAzureOIDCConfigureScript(t *testing.T) {
+ t.Parallel()
+ isBadParamErrFn := func(tt require.TestingT, err error, i ...any) {
+ require.True(tt, trace.IsBadParameter(err), "expected bad parameter, got %v", err)
+ }
+
+ ctx := context.Background()
+ env := newWebPack(t, 1)
+
+ proxyAddr := env.proxies[0].webURL.String()
+
+ // Unauthenticated client for script downloading.
+ publicClt := env.proxies[0].newClient(t)
+ pathVars := []string{
+ "webapi",
+ "scripts",
+ "integrations",
+ "configure",
+ "azureoidc.sh",
+ }
+ endpoint := publicClt.Endpoint(pathVars...)
+
+ tests := []struct {
+ name string
+ reqQuery url.Values
+ errCheck require.ErrorAssertionFunc
+ expectedTeleportArgs string
+ }{
+ {
+ name: "valid",
+ reqQuery: url.Values{
+ "integrationName": []string{"myintegration"},
+ "authConnectorName": []string{"myconnector"},
+ "accessGraph": []string{"true"},
+ },
+ errCheck: require.NoError,
+ expectedTeleportArgs: "integration configure azure-oidc " +
+ `--proxy-public-addr=` + proxyAddr + ` ` +
+ `--auth-connector-name=myconnector ` +
+ `--access-graph`,
+ },
+ {
+ name: "valid without accessGraph",
+ reqQuery: url.Values{
+ "integrationName": []string{"myintegration"},
+ "authConnectorName": []string{"myconnector"},
+ },
+ errCheck: require.NoError,
+ expectedTeleportArgs: "integration configure azure-oidc " +
+ `--proxy-public-addr=` + proxyAddr + ` ` +
+ `--auth-connector-name=myconnector`,
+ },
+ {
+ name: "integrationName invalid",
+ reqQuery: url.Values{
+ "integrationName": []string{"myintegration;"},
+ "authConnectorName": []string{"myconnector"},
+ },
+ errCheck: isBadParamErrFn,
+ },
+ {
+ name: "authConnectorName invalid",
+ reqQuery: url.Values{
+ "integrationName": []string{"myintegration"},
+ "authConnectorName": []string{"myconnector;"},
+ },
+ errCheck: isBadParamErrFn,
+ },
+ {
+ name: "integrationName missing",
+ reqQuery: url.Values{
+ "authConnectorName": []string{"myconnector"},
+ },
+ errCheck: isBadParamErrFn,
+ },
+ {
+ name: "authConnectorName missing",
+ reqQuery: url.Values{
+ "integrationName": []string{"myintegration"},
+ },
+ errCheck: isBadParamErrFn,
+ },
+ }
+
+ for _, tc := range tests {
+ tc := tc
+ t.Run(tc.name, func(t *testing.T) {
+ resp, err := publicClt.Get(ctx, endpoint, tc.reqQuery)
+ tc.errCheck(t, err)
+ if err != nil {
+ return
+ }
+
+ require.Contains(t, string(resp.Bytes()),
+ fmt.Sprintf("teleportArgs='%s'\n", tc.expectedTeleportArgs),
+ )
+ })
+ }
+}
diff --git a/tool/teleport/common/integration_configure.go b/tool/teleport/common/integration_configure.go
index 6aa51cc25894e..fe642f1117fd0 100644
--- a/tool/teleport/common/integration_configure.go
+++ b/tool/teleport/common/integration_configure.go
@@ -20,6 +20,7 @@ package common
import (
"context"
+ "fmt"
"log/slog"
awsConfig "github.com/aws/aws-sdk-go-v2/config"
@@ -34,6 +35,7 @@ import (
"github.com/gravitational/teleport/lib"
"github.com/gravitational/teleport/lib/config"
"github.com/gravitational/teleport/lib/integrations/awsoidc"
+ "github.com/gravitational/teleport/lib/integrations/azureoidc"
"github.com/gravitational/teleport/lib/integrations/externalauditstorage"
"github.com/gravitational/teleport/lib/integrations/externalauditstorage/easconfig"
"github.com/gravitational/teleport/lib/integrations/samlidp"
@@ -218,6 +220,32 @@ func onIntegrationConfAccessGraphAWSSync(ctx context.Context, params config.Inte
return trace.Wrap(awsoidc.ConfigureAccessGraphSyncIAM(ctx, iamClient, confReq))
}
+func onIntegrationConfAzureOIDCCmd(ctx context.Context, params config.IntegrationConfAzureOIDC) error {
+ // Ensure we print output to the user. LogLevel at this point was set to Error.
+ utils.InitLogger(utils.LoggingForDaemon, slog.LevelInfo)
+
+ appID, tenantID, err := azureoidc.SetupEnterpriseApp(ctx, params.ProxyPublicAddr, params.AuthConnectorName)
+ if err != nil {
+ return trace.Wrap(err)
+ }
+
+ if params.AccessGraphEnabled {
+ err := azureoidc.CreateTAGCacheFile(ctx)
+ if err != nil {
+ return trace.Wrap(err)
+ }
+ }
+
+ fmt.Println()
+ fmt.Println("Success! Use the following information to finish the integration onboarding in Teleport:")
+ fmt.Printf("Tenant ID: %s\nClient ID: %s\n", tenantID, appID)
+ if params.AccessGraphEnabled {
+ fmt.Println("To finish the setup you will need the `cache.json` file that we created for you.")
+ fmt.Println("Use `download cache.json` to download it from the Azure Cloud Shell, and submit it on the integration onboarding page.")
+ }
+ return nil
+}
+
func onIntegrationConfSAMLIdPGCPWorkforce(ctx context.Context, params samlidpconfig.GCPWorkforceAPIParams) error {
// Ensure we print output to the user. LogLevel at this point was set to Error.
utils.InitLogger(utils.LoggingForDaemon, slog.LevelInfo)
diff --git a/tool/teleport/common/teleport.go b/tool/teleport/common/teleport.go
index 50efba3ffe186..4b4ed1267b7b4 100644
--- a/tool/teleport/common/teleport.go
+++ b/tool/teleport/common/teleport.go
@@ -515,6 +515,11 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con
integrationConfExternalAuditCmd.Flag("glue-table", "The name of the Glue table used.").Required().StringVar(&ccf.IntegrationConfExternalAuditStorageArguments.GlueTable)
integrationConfExternalAuditCmd.Flag("aws-partition", "AWS partition (default: aws).").Default("aws").StringVar(&ccf.IntegrationConfExternalAuditStorageArguments.Partition)
+ integrationConfAzureOIDCCmd := integrationConfigureCmd.Command("azure-oidc", "Configures Azure / Entra ID OIDC integration")
+ integrationConfAzureOIDCCmd.Flag("proxy-public-addr", "The public address of Teleport Proxy Service").Required().StringVar(&ccf.IntegrationConfAzureOIDCArguments.ProxyPublicAddr)
+ integrationConfAzureOIDCCmd.Flag("auth-connector-name", "The name of Entra ID SAML Auth connector in Teleport.").Required().StringVar(&ccf.IntegrationConfAzureOIDCArguments.AuthConnectorName)
+ integrationConfAzureOIDCCmd.Flag("access-graph", "Enable Access Graph integration.").BoolVar(&ccf.IntegrationConfAzureOIDCArguments.AccessGraphEnabled)
+
integrationConfSAMLIdP := integrationConfigureCmd.Command("samlidp", "Manage SAML IdP integrations.")
integrationSAMLIdPGCPWorkforce := integrationConfSAMLIdP.Command("gcp-workforce", "Configures GCP Workforce Identity Federation pool and SAML provider.")
integrationSAMLIdPGCPWorkforce.Flag("org-id", "GCP organization ID.").Required().StringVar(&ccf.IntegrationConfSAMLIdPGCPWorkforceArguments.OrganizationID)
@@ -640,6 +645,8 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con
err = onIntegrationConfExternalAuditCmd(ctx, ccf.IntegrationConfExternalAuditStorageArguments)
case integrationConfTAGSyncCmd.FullCommand():
err = onIntegrationConfAccessGraphAWSSync(ctx, ccf.IntegrationConfAccessGraphAWSSyncArguments)
+ case integrationConfAzureOIDCCmd.FullCommand():
+ err = onIntegrationConfAzureOIDCCmd(ctx, ccf.IntegrationConfAzureOIDCArguments)
case integrationSAMLIdPGCPWorkforce.FullCommand():
err = onIntegrationConfSAMLIdPGCPWorkforce(ctx, ccf.IntegrationConfSAMLIdPGCPWorkforceArguments)
case tpmIdentifyCmd.FullCommand():