Skip to content

Commit

Permalink
Merge pull request #539 from atsign-foundation/noports_core_unit_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gkc authored Nov 10, 2023
2 parents adfef6b + 78693f4 commit ba56ff7
Show file tree
Hide file tree
Showing 74 changed files with 3,557 additions and 2,129 deletions.
166 changes: 0 additions & 166 deletions .github/workflows/end2end_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,172 +192,6 @@ jobs:
docker compose down
# Test suite 2
# Installer tests (local vs installer)
e2e_installer_test:
# Don't run on forks (cause no secrets), don't run if dependebot (cause no secrets)
if: ${{ github.event.pull_request.head.repo.fork == false && github.actor != 'dependabot[bot]'}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
np: [local, installer]
npd: [local, installer]
exclude:
# Don't run these against themselves, pointless to test
- np: local
npd: local
steps:
- name: Show Matrix Values
run: |
echo "job index: ${{ strategy.job-index }}"
echo "np: ${{ matrix.np }}"
echo "npd: ${{ matrix.npd }}"
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Setup Devicename
# First two guarantee a unique # per workflow call
# Last two guarantee a unique # per job per strategy in matrix
run: |
echo "DEVICENAME=${{ github.run_id }}${{ github.run_attempt }}2${{ strategy.job-index }}" >> $GITHUB_ENV
- name: Setup NP/NPD key env
run: |
SSHNP_ATKEYS="$(tr '[:lower:]' '[:upper:]' <<< '${{ env.SSHNP_ATSIGN }}')"
echo "SSHNP_ATKEYS=ATKEYS_${SSHNP_ATKEYS:1}" >> $GITHUB_ENV
SSHNPD_ATKEYS="$(tr '[:lower:]' '[:upper:]' <<< '${{ env.SSHNPD_ATSIGN }}')"
echo "SSHNPD_ATKEYS=ATKEYS_${SSHNPD_ATKEYS:1}" >> $GITHUB_ENV
- name: Setup NP/NPD keys
working-directory: tests/end2end_tests/contexts
run: |
echo "${{ secrets[env.SSHNP_ATKEYS] }}" > sshnp/.atsign/keys/${{ env.SSHNP_ATSIGN }}_key.atKeys
echo "${{ secrets[env.SSHNPD_ATKEYS] }}" > sshnpd/.atsign/keys/${{ env.SSHNPD_ATSIGN }}_key.atKeys
- name: Set up entrypoints
uses: ./.github/composite/setup_entrypoints
with:
sshnp: ${{ matrix.np }}
sshnp_atsign: ${{ env.SSHNP_ATSIGN }}
sshnpd: ${{ matrix.npd }}
sshnpd_atsign: ${{ env.SSHNPD_ATSIGN }}
sshrvd_atsign: ${{ env[env.PROD_RVD_ATSIGN] }}
devicename: ${{ env.DEVICENAME }}

- name: Ensure entrypoints exist
working-directory: tests/end2end_tests/contexts
run: |
cat sshnp/entrypoint.sh
cat sshnpd/entrypoint.sh
cat sshrvd/entrypoint.sh
- name: Create docker-compose.yaml
working-directory: tests/end2end_tests/tests
run: |
cat docker-compose-base.yaml > docker-compose.yaml
- name: Add runtime-sshnp-installer image to docker-compose.yaml
working-directory: tests/end2end_tests/tests
if: ${{ matrix.np == 'installer' }}
run: |
cat service-image-runtime-sshnp-installer.yaml >> docker-compose.yaml
echo ' - client_atsign="${{ env.SSHNP_ATSIGN }}"' >> docker-compose.yaml
echo ' - device_atsign="${{ env.SSHNPD_ATSIGN }}"' >> docker-compose.yaml
echo ' - host_atsign="${{ env[env.PROD_RVD_ATSIGN] }}"' >> docker-compose.yaml
echo ' image: atsigncompany/sshnp-e2e-runtime:sshnp-installer' >> docker-compose.yaml
- name: Add runtime-sshnpd-installer image to docker-compose.yaml
working-directory: tests/end2end_tests/tests
if: ${{ matrix.npd == 'installer' }}
run: |
cat service-image-runtime-sshnpd-installer.yaml >> docker-compose.yaml
echo ' - client_atsign="${{ env.SSHNP_ATSIGN }}"' >> docker-compose.yaml
echo ' - device_atsign="${{ env.SSHNPD_ATSIGN }}"' >> docker-compose.yaml
echo ' - device_name=${{ env.DEVICENAME }}' >> docker-compose.yaml
echo ' image: atsigncompany/sshnp-e2e-runtime:sshnpd-installer' >> docker-compose.yaml
- name: Add container-sshnp to docker-compose.yaml
working-directory: tests/end2end_tests/tests
run: |
# Add the base service
cat service-container-sshnp.yaml >> docker-compose.yaml
# Add the runtime
if [ "${{ matrix.np }}" = 'installer' ]; then
echo ' image: atsigncompany/sshnp-e2e-runtime:sshnp-installer' >> docker-compose.yaml
else
echo ' image: atsigncompany/sshnp-e2e-runtime:${{ matrix.np }}' >> docker-compose.yaml
fi
# Add the dependencies
echo ' depends_on:' >> docker-compose.yaml
echo ' container-sshnpd:' >> docker-compose.yaml
echo ' condition: service_healthy' >> docker-compose.yaml
if [ "${{ matrix.np }}" = 'installer' ]; then
echo ' image-runtime-sshnp-installer:' >> docker-compose.yaml
else
echo ' image-runtime-local:' >> docker-compose.yaml
fi
echo ' condition: service_started' >> docker-compose.yaml
- name: Add container-sshnpd to docker-compose.yaml
working-directory: tests/end2end_tests/tests
run: |
# Add the base service
cat service-container-sshnpd.yaml >> docker-compose.yaml
# Add the runtime
if [ "${{ matrix.npd }}" = 'installer' ]; then
echo ' image: atsigncompany/sshnp-e2e-runtime:sshnpd-installer' >> docker-compose.yaml
else
echo ' image: atsigncompany/sshnp-e2e-runtime:${{ matrix.npd }}' >> docker-compose.yaml
fi
# Add the dependencies
echo ' depends_on:' >> docker-compose.yaml
if [ "${{ matrix.npd }}" = 'installer' ]; then
echo ' - image-runtime-sshnpd-installer' >> docker-compose.yaml
else
echo ' - image-runtime-local' >> docker-compose.yaml
fi
- name: docker-compose.yaml
if: always()
working-directory: tests/end2end_tests/tests
run: |
cat docker-compose.yaml
- name: Build
working-directory: tests/end2end_tests/tests
run: |
docker compose build
- name: Test
working-directory: tests/end2end_tests/tests
run: |
${{ env.DOCKER_COMPOSE_UP_CMD }}
- name: Logs
if: always()
working-directory: tests/end2end_tests/tests
run: |
docker compose ps -a
docker compose logs --timestamps
- name: Found "Test Passed" in Logs
if: always()
working-directory: tests/end2end_tests/tests
run: |
docker compose logs --timestamps | grep -q "Test Passed$"
- name: Tear down
# Always tear down outside of the act environment
# but don't tear down on failure in the act environment
if: ${{ !env.ACT }} || success()
working-directory: tests/end2end_tests/tests
run: |
docker compose down
# Test suite 3
# Backward compatibility tests
e2e_release_test:
# Don't run on push and on pull, meant to be ran manually (workflow dispatch)
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/unit_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ jobs:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: ./.github/composite/verify_cli_tags
noports_core-unit_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # v1.6.0
- name: dart pub get
working-directory: packages/noports_core
run: dart pub get
- name: dart analyze
working-directory: packages/noports_core
run: dart analyze
- name: dart test
working-directory: packages/noports_core
run: dart test
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,38 @@ import 'dart:async';
import 'dart:convert';

import 'package:dartssh2/dartssh2.dart';
import 'package:meta/meta.dart';
import 'package:noports_core/sshnp.dart';
import 'package:noports_core/utils.dart';
import 'package:path/path.dart' as path;

export 'ssh_key_utils/dart_ssh_key_util.dart';
export 'ssh_key_utils/local_ssh_key_util.dart';
export 'dart_ssh_key_util.dart';
export 'local_ssh_key_util.dart';

class AtSSHKeyPair {
@protected
abstract interface class AtSshKeyUtil {
FutureOr<AtSshKeyPair> generateKeyPair({
required String identifier,
SupportedSshAlgorithm algorithm,
});

FutureOr<AtSshKeyPair> getKeyPair({
required String identifier,
});

FutureOr<dynamic> addKeyPair({
required AtSshKeyPair keyPair,
required String identifier,
});

FutureOr<dynamic> deleteKeyPair({
required String identifier,
});
}

class AtSshKeyPair {
final SSHKeyPair keyPair;
final String identifier;

AtSSHKeyPair.fromPem(
AtSshKeyPair.fromPem(
String pemText, {
required String identifier,
String? directory,
Expand All @@ -34,20 +52,4 @@ class AtSSHKeyPair {

String get privateKeyFileName => identifier;
String get publicKeyFileName => '$privateKeyFileName.pub';

// TODO consider adding this function
// void destroy() {
// throw UnimplementedError();
// }
}

abstract interface class AtSSHKeyUtil {
FutureOr<AtSSHKeyPair> generateKeyPair({
required String identifier,
SupportedSSHAlgorithm algorithm,
});

FutureOr<AtSSHKeyPair> getKeyPair({
required String identifier,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,58 @@ import 'package:cryptography/cryptography.dart';
import 'package:noports_core/utils.dart';
import 'package:openssh_ed25519/openssh_ed25519.dart';

class DartSSHKeyUtil implements AtSSHKeyUtil {
static final Map<String, AtSSHKeyPair> _keyPairCache = {};
class DartSshKeyUtil implements AtSshKeyUtil {
static final Map<String, AtSshKeyPair> _keyPairCache = {};

@override
Future<AtSSHKeyPair> generateKeyPair({
Future<AtSshKeyPair> generateKeyPair({
required String identifier,
SupportedSSHAlgorithm algorithm = DefaultArgs.sshAlgorithm,
SupportedSshAlgorithm algorithm = DefaultArgs.sshAlgorithm,
}) async {
AtSSHKeyPair keyPair;
AtSshKeyPair keyPair;
switch (algorithm) {
case SupportedSSHAlgorithm.rsa:
case SupportedSshAlgorithm.rsa:
keyPair = _generateRSAKeyPair(identifier);
case SupportedSSHAlgorithm.ed25519:
case SupportedSshAlgorithm.ed25519:
keyPair = await _generateEd25519KeyPair(identifier);
}
_keyPairCache[identifier] = keyPair;
return keyPair;
}

@override
Future<AtSSHKeyPair> getKeyPair({required String identifier}) async {
return _keyPairCache[identifier] ?? await generateKeyPair(identifier: identifier);
Future<AtSshKeyPair> getKeyPair({required String identifier}) async {
return _keyPairCache[identifier] ??
await generateKeyPair(identifier: identifier);
}

AtSSHKeyPair _generateRSAKeyPair(String identifier) => AtSSHKeyPair.fromPem(
AtSshKeyPair _generateRSAKeyPair(String identifier) => AtSshKeyPair.fromPem(
AtChopsUtil.generateRSAKeyPair(keySize: 4096).privateKey.toPEM(),
identifier: identifier,
);

Future<AtSSHKeyPair> _generateEd25519KeyPair(String identifier) async {
Future<AtSshKeyPair> _generateEd25519KeyPair(String identifier) async {
var keyPair2 = await Ed25519().newKeyPair();
var pemText = encodeEd25519Private(
privateBytes: await keyPair2.extractPrivateKeyBytes(),
publicBytes: (await keyPair2.extractPublicKey()).bytes,
);
return AtSSHKeyPair.fromPem(
return AtSshKeyPair.fromPem(
pemText,
identifier: identifier,
);
}

@override
FutureOr addKeyPair({
required AtSshKeyPair keyPair,
required String identifier,
}) {
_keyPairCache[identifier] = keyPair;
}

@override
FutureOr deleteKeyPair({required String identifier}) {
_keyPairCache.remove(identifier);
}
}
Loading

0 comments on commit ba56ff7

Please sign in to comment.