Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b3f5658
updated network fabric extension to reflect version 2024-02-15-preview
Nov 14, 2024
f9726fb
updates based on code review
Nov 15, 2024
3b12808
version updated to 7.0.0
Nov 18, 2024
1c0f544
Merge branch 'Azure:main' into main
nafizhaider32 Nov 18, 2024
d0e45eb
fix linting
Nov 18, 2024
1b9b959
Merge branch 'main' of https://github.com/nafizhaider32/azure-cli-ext…
Nov 18, 2024
995e948
Merge branch 'Azure:main' into main
nafizhaider32 Nov 19, 2024
8b75aea
Merge branch 'Azure:main' into main
nafizhaider32 Nov 20, 2024
09efafd
Merge branch 'Azure:main' into main
nafizhaider32 Nov 25, 2024
5b0f72e
Merge branch 'Azure:main' into main
nafizhaider32 Feb 7, 2025
a66c6aa
new api changes
Feb 7, 2025
d5de533
Merge branch 'Azure:main' into main
nafizhaider32 Feb 18, 2025
941f0cf
Update for bugfix with 7.1 CLI
Feb 18, 2025
102fe25
fixing lint issue
Feb 18, 2025
9526316
aligning with new api short description
Feb 18, 2025
189b131
reverting version change
Feb 19, 2025
9d89164
Merge branch 'Azure:main' into main
nafizhaider32 Feb 19, 2025
f3add59
Merge branch 'Azure:main' into main
nafizhaider32 Feb 26, 2025
aad4f37
new cli version for network fabric
Feb 26, 2025
1b8d995
lint fixes
Feb 27, 2025
4c0167d
fixing lint rule
Feb 27, 2025
ffb4de1
Merge branch 'Azure:main' into main
nafizhaider32 Feb 27, 2025
55fe999
fix
Feb 27, 2025
6f4dba2
Merge branch 'main' of https://github.com/nafizhaider32/azure-cli-ext…
Feb 27, 2025
c96ef5c
testing yaml update again
Feb 27, 2025
1d9ac55
some more updates
Feb 27, 2025
51c93a7
nf create lint rules
Feb 27, 2025
642d5b7
internal network lint rule
Feb 27, 2025
f5f714f
last lint rules
Feb 27, 2025
36af23d
fix file name
Feb 27, 2025
704323e
fix password scan
Feb 27, 2025
5b4bc53
updated to say redacted
Feb 28, 2025
79c2289
Merge branch 'Azure:main' into main
nafizhaider32 Feb 28, 2025
bdfab4c
fix redacted with quotes
Feb 28, 2025
d848569
Merge branch 'main' of https://github.com/nafizhaider32/azure-cli-ext…
Feb 28, 2025
eb889b8
this is the one
Feb 28, 2025
74126a2
Merge branch 'Azure:main' into main
nafizhaider32 Mar 17, 2025
3a14bfa
Merge branch 'Azure:main' into main
nafizhaider32 Mar 26, 2025
f8a88f1
updating nexus identity
Mar 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/nexusidentity/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

1.0.0b5
+++++++
* Adding support for older algorithm ssh keys

1.0.0b4
+++++++
* Adding support for Linux platform
Expand Down
25 changes: 25 additions & 0 deletions src/nexusidentity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Azure CLI nexusidentity Extension #

This is an extension to Azure CLI to manage nexusidentity resources.

## How to use ##

Install the extension:

```
az extension add --name nexusidentity
```

Validate that the extension is installed correctly:

```
az nexusidentity --help
```

## Included Features ##

Below is a high-level overview of nexusidentity commands.

| Commands | Description |
|---------------------------|------------------------|
| az nexusidentity gen-keys | Manage key generation. |
5 changes: 0 additions & 5 deletions src/nexusidentity/README.rst

This file was deleted.

12 changes: 6 additions & 6 deletions src/nexusidentity/azext_nexusidentity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ class NexusidentityCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
from azure.cli.core.commands import CliCommandType

custom_command_type = CliCommandType(
operations_tmpl='azext_nexusidentity.custom#{}')
super(
NexusidentityCommandsLoader,
self).__init__(
cli_ctx=cli_ctx,
custom_command_type=custom_command_type)
operations_tmpl="azext_nexusidentity.custom#{}"
)
super().__init__(cli_ctx=cli_ctx, custom_command_type=custom_command_type)

def load_command_table(self, args):
from azext_nexusidentity.commands import load_command_table

load_command_table(self, args)
return self.command_table

def load_arguments(self, command):
from azext_nexusidentity._params import load_arguments

load_arguments(self, command)


Expand Down
3 changes: 3 additions & 0 deletions src/nexusidentity/azext_nexusidentity/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@
helps['nexusidentity gen-keys'] = """
type: command
short-summary: Generate Nexusidentity keys.
parameters:
- name: --algorithm
short-summary: Algorithm to use for generating keys. It can either be ecdsa-sk or ed25519-sk
"""
15 changes: 13 additions & 2 deletions src/nexusidentity/azext_nexusidentity/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@
# pylint: disable=unused-import

from knack.arguments import CLIArgumentType
from azure.cli.core.commands.parameters import get_enum_type


def load_arguments(_, __):
pass
def load_arguments(self, _):
with self.argument_context("nexusidentity gen-keys") as c:
c.argument(
"algorithm",
arg_type=get_enum_type(
[
"ed25519-sk",
"ecdsa-sk",
]
),
help="Algorithm to use for generating keys. It can either be ecdsa-sk or ed25519-sk",
)
4 changes: 2 additions & 2 deletions src/nexusidentity/azext_nexusidentity/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@


def load_command_table(self, _):
with self.command_group('nexusidentity') as g:
g.custom_command('gen-keys', 'generate_nexus_identity_keys')
with self.command_group("nexusidentity") as g:
g.custom_command("gen-keys", "generate_nexus_identity_keys")
98 changes: 60 additions & 38 deletions src/nexusidentity/azext_nexusidentity/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
# pylint: disable=too-many-statements

import logging

from knack.util import CLIError # pylint: disable=unused-import
from knack.log import get_logger

import logging

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = get_logger(__name__)


def generate_nexus_identity_keys() -> None:
def generate_nexus_identity_keys(algorithm=None):

import os
import subprocess
Expand All @@ -30,6 +31,13 @@ def generate_nexus_identity_keys() -> None:
# Generate SSH key
if sys.platform.startswith("win") or sys.platform.startswith("linux"):

algoToBeUsed = "ed25519-sk"
key_name = "id_ed25519_sk"

if algorithm and algorithm == "ecdsa-sk":
algoToBeUsed = "ecdsa-sk"
key_name = "id_ecdsa_sk"

if sys.platform.startswith("win"):
dir_path = os.path.expanduser("~\\.ssh")
elif sys.platform.startswith("linux"):
Expand All @@ -42,54 +50,63 @@ def generate_nexus_identity_keys() -> None:
os.makedirs(dir_path)
except OSError as e:
logger.error("Error creating directory: %s", e)
raise CLIError(f"Error creating directory: {e}")
raise CLIError(f"Error creating directory: {e}") from e

# Generate ed25519-sk key
subprocess.run(['ssh-keygen',
'-t',
'ed25519-sk',
'-O',
'resident',
'-O',
'verify-required',
'-f',
os.path.join(dir_path, "id_ed25519_sk")],
check=False)

# read the key from the file
subprocess.run(
[
"ssh-keygen",
"-t",
algoToBeUsed,
"-O",
"resident",
"-O",
"verify-required",
"-C",
"NexusIdentitySSHKey",
"-f",
os.path.join(dir_path, key_name),
],
check=False,
)

# read the key from the file
try:
# Read public key
with open(os.path.join(dir_path, "id_ed25519_sk.pub"), "r") as key_file:
file_path = key_name + ".pub"
with open(
os.path.join(dir_path, file_path), "r", encoding="utf-8"
) as key_file:
public_key = key_file.read()
except FileNotFoundError as e:
raise CLIError(f"Error reading public key: {e}")
raise CLIError(f"Error reading public key: {e}") from e
except OSError as e:
raise CLIError(f"Unexpected error reading public key: {e}")
raise CLIError(f"Unexpected error reading public key: {e}") from e

try:
credential = AzureCliCredential()
scopes = ['https://graph.microsoft.com//.default']
graph_client = GraphServiceClient(
credentials=credential, scopes=scopes)
scopes = ["https://graph.microsoft.com//.default"]
graph_client = GraphServiceClient(credentials=credential, scopes=scopes)

except ClientAuthenticationError as e:
logger.error("Authentication failed: %s", e)
raise CLIError(f"Authentication failed: {e}")
raise CLIError(f"Authentication failed: {e}") from e
except Exception as e:
logger.error("An unexpected error occurred: %s", e)
raise CLIError(f"An unexpected error occurred: {e}")
raise CLIError(f"An unexpected error occurred: {e}") from e

async def me():
extension_id = "com.nexusidentity.keys"

# Get user object
user = await graph_client.me.get()

# Get extensions assoicated with the user
# Get extensions associated with the user
extensions = await graph_client.me.extensions.get()

extension_exists = any(
extension.id == extension_id for extension in extensions.value)
extension.id == extension_id for extension in extensions.value
)

try:
# Update or create extension
Expand All @@ -98,31 +115,36 @@ async def me():
odata_type="microsoft.graph.openTypeExtension",
additional_data={
"extension_name": extension_id,
"publicKey": public_key
}
"publicKey": public_key,
},
)
await graph_client.me.extensions.by_extension_id(extension_id).patch(request_body)
await graph_client.me.extensions.by_extension_id(
extension_id
).patch(request_body)

print(f"Successfully updated public key to Microsoft Entra Id account {user.mail}")
print(
f"Successfully updated public key to Microsoft Entra Id account {user.mail}"
)
else:
request_body = OpenTypeExtension(
odata_type="microsoft.graph.openTypeExtension",
extension_name=extension_id,
additional_data={
"publicKey": public_key
}
additional_data={"publicKey": public_key},
)
await graph_client.me.extensions.post(request_body)

print(f"Successfully uploaded public key to Microsoft Entra Id account {user.mail}")
print(
f"Successfully uploaded public key to Microsoft Entra Id account {user.mail}"
)
except ODataError as e:
logger.error("Error updating extension: %s", e)
raise CLIError(f"Error updating extension: {e}")
except (HttpResponseError) as e:
raise CLIError(f"Error updating extension: {e}") from e
except HttpResponseError as e:
logger.error("Failed to update or create extension: %s", e)
raise CLIError(f"Failed to update or create extension: {e}")
raise CLIError(f"Failed to update or create extension: {e}") from e

asyncio.run(me())
else:
logger.warning(
"This command is currently supported only on Windows and linux platforms")
"This command is currently supported only on Windows and linux platforms"
)
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,4 @@ interactions:
status:
code: 204
message: No Content
version: 1
version: 1
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,45 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

'''
"""
Nexus Identity Ssh-Key Geneation Scenario Test
'''
"""

from azure.cli.testsdk import ScenarioTest, ResourceGroupPreparer, live_only


def setup_scenario1(test):
''' Env setup_scenario1 '''
"""Env setup_scenario1"""
pass


def cleanup_scenario1(test):
'''Env cleanup_scenario1 '''
"""Env cleanup_scenario1"""
pass


def call_scenario1(test):
''' # Testcase: scenario1'''
"""# Testcase: scenario1"""
setup_scenario1(test)
step_gen_keys(test, checks=[])
cleanup_scenario1(test)


def step_gen_keys(test, checks=None):
'''Generate Nexus Identity ssh keys '''
"""Generate Nexus Identity ssh keys"""
if checks is None:
checks = []
test.cmd('az nexusidentity gen-keys')
test.cmd("az nexusidentity gen-keys")
test.cmd("az nexusidentity gen-keys --algorithm ecdsa-sk")
test.cmd("az nexusidentity gen-keys --algorithm ed25519-sk")


class NexusidentityScenarioTest(ScenarioTest):
''' Nexus Identity Ssh-Key Generation Scenario Test '''
"""Nexus Identity Ssh-Key Generation Scenario Test"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

@live_only()
def test_nexusidentity_scenario1(self):

Expand Down
4 changes: 2 additions & 2 deletions src/nexusidentity/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# TODO: Confirm this is the right version number you want and it matches your
# HISTORY.rst entry.
VERSION = '1.0.0b4'
VERSION = '1.0.0b5'

# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand All @@ -38,7 +38,7 @@
'msgraph-sdk'
]

with open('README.rst', 'r', encoding='utf-8') as f:
with open('README.md', 'r', encoding='utf-8') as f:
README = f.read()
with open('HISTORY.rst', 'r', encoding='utf-8') as f:
HISTORY = f.read()
Expand Down
2 changes: 1 addition & 1 deletion src/service_name.json
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@
{
"Command": "az nexusidentity",
"AzureServiceName": "Nexus Identity",
"URL": ""
"URL": "https://learn.microsoft.com/en-us/azure/operator-nexus/"
},
{
"Command": "az storage-actions",
Expand Down
Loading