cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1695
Views
1
Helpful
18
Replies

Devices with MFA

sm000x
Level 1
Level 1

Hi:

My company will convert the devices to MFA (Multi Factor Authentication) soon.
My question is how to make NSO use MFA to the device?

I searched the src/ncs/yang and found that in tailf-ncs-devices.yang there is
container devices {
  container authgroups {
    list group {
      grouping remote-user-remote-auth {
        leaf callback-node {...}
        leaf action-name {...}
      }
    }
  }
}

will that help to have NSO to use MFA to the device?

I need some example java code how to use callback-node and action-name.
Does any one have experience?

THX
sm000x

1 Accepted Solution

Accepted Solutions

perander
Cisco Employee
Cisco Employee

Hi!

This is probably not supported out of the box with NSO today.
I asked around at the department, and it doesn't seem like it
is possible to give a proper short answer on devhub at least.

However, it looks like an interesting use case and I suggest
raising a case to discuss it further so we can help you properly.

View solution in original post

18 Replies 18

perander
Cisco Employee
Cisco Employee

Hi!

This is probably not supported out of the box with NSO today.
I asked around at the department, and it doesn't seem like it
is possible to give a proper short answer on devhub at least.

However, it looks like an interesting use case and I suggest
raising a case to discuss it further so we can help you properly.

Hi, Perander:

Thank you so much for the reply.

"....I suggest raising a case ...."
How do I create a case?

THX
sm000x

Hi!

Through your NSO support channel, raise a feature request or a support case.

EDIT: There is actually a link on the right you can use "Open a TAC case".

I see.

Thank you
sm000x

cohult
Cisco Employee
Cisco Employee

A quick MFA example:

$ source /path/to/nso/ncsrc
$ ls -1
Makefile
auth.pl
response.pl
$ make all start 

Browse to 127.0.0.1:8080

Username: admin
Password: admin
challenge: sendSMScode
challenge: secretSMScode

user/pass oper will login using local authentication.

Makefile:

NSO_RUN_DIR=nso-rundir

EXTRA_NCS_LOG_CONFIG=\n\ \ \ \ \<webui-browser-log>\n\
\ \ \ \ \ <enabled>true</enabled>\n\
\ \ \ \ \ <filename>./logs/webui-browser.log</filename>\n\
\ \ \ </webui-browser-log>\n\ \ \

EXTRA_AAA_CONFIG=\ \ <auth-order>external-authentication local-authentication pam</auth-order>\n\
\ \ \ <external-authentication>\n\
\ \ \ \ \ <enabled>true</enabled>\n\
\ \ \ \ \ <executable>./auth.pl</executable>\n\
\ \ \ \ \ <use-base64>false</use-base64>\n\
\ \ \ </external-authentication>\n\
\ \ \ <challenge-order>external-challenge</challenge-order>\n\
\ \ \ <external-challenge>\n\
\ \ \ \ \ <enabled>true</enabled>\n\
\ \ \ \ \ <executable>./response.pl</executable>\n\
\ \ \ \ \ <use-base64>false</use-base64>\n\
\ \ \ </external-challenge>\n\ \ \

all:
	ncs-setup --no-netsim --dest $(NSO_RUN_DIR)
	sed -i.bak -e '/<external-authentication>/I,+3 d' \
             -e "s|</logs>|$(EXTRA_NCS_LOG_CONFIG)</logs>|" \
             -e "s|</aaa>|$(EXTRA_AAA_CONFIG)</aaa>|" \
             $(NSO_RUN_DIR)/ncs.conf
	cp *.pl $(NSO_RUN_DIR)/

clean:
	rm -rf $(NSO_RUN_DIR)

stop:
	ncs --stop || true

start: stop
	cd $(NSO_RUN_DIR); \
	ncs  

auth.pl:

#!/usr/bin/perl

$base64 = 0;
$extra = 0;
while (@ARGV) {
    if ($ARGV[0] eq "-b") {
        $base64 = 1;
    } elsif ($ARGV[0] eq "-e") {
        $extra = 1;
    }
    shift @ARGV;
}

if ((!$extra && (<STDIN> =~ /^\[([^;]+);([^;]+);\]$/)) ||
    ($extra &&
     (<STDIN> =~ /^\[([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);\]$/))) {
    if ($base64) {
        $user = decode_b64($1);
        $pass = decode_b64($2);
    } else {
        $user = $1;
        $pass = $2;
    }
    if ($extra) {
        $ip = $3;
        $port = $4;
        $ctx = $5;
        $proto = $6;
    }
    if ($user eq "admin") {
        if ($extra && ($ip ne "0.0.0.0" || $port ne "0" ||
                       $ctx ne "maapi" || $proto ne "unknown")) {
            print "abort Bad extra $ip $port $ctx $proto\n";
        } else {
            if ($pass eq "admin") {
                #2> base64:encode("bla bla\nbla bla\nChallenge prompt1\n").
                #<<"YmxhIGJsYQpibGEgYmxhCkNoYWxsZW5nZSBwcm9tcHQxCg==">>
                print "challenge challengeId1 YmxhIGJsYQpibGEgYmxhCkNoYWxsZW5nZSBwcm9tcHQxCg==\n";
            } else {
                print "reject Bad password for admin\n";
            }
        }
    }
}
# else exit silently

sub decode_b64 {
    my $str = shift;
    my $res = "";

    $str =~ tr|A-Za-z0-9+/||cd;             # remove non-base64 chars (padding)
    $str =~ tr|A-Za-z0-9+/| -_|;            # convert to uuencoded format
    while ($str =~ /(.{1,60})/gs) {
        my $len = chr(32 + length($1)*3/4); # compute length byte
        $res .= unpack("u", $len . $1 );    # uudecode
    }
    $res;
} 

response.pl:

#!/usr/bin/perl

$base64 = 0;
$extra = 0;
while (@ARGV) {
    if ($ARGV[0] eq "-b") {
        $base64 = 1;
    } elsif ($ARGV[0] eq "-e") {
        $extra = 1;
    }
    shift @ARGV;
}

if ((!$extra && (<STDIN> =~ /^\[([^;]+);([^;]+);\]$/)) ||
    ($extra &&
     (<STDIN> =~ /^\[([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);\]$/))) {
    if ($base64) {
        $challenge_id = decode_b64($1);
        $response = decode_b64($2);
    } else {
        $challenge_id = $1;
        $response = $2;
    }
    if ($extra) {
        $ip = $3;
        $port = $4;
        $ctx = $5;
        $proto = $6;
    }
    if ($challenge_id eq "challengeId1") {
        if ($extra && ($ip ne "0.0.0.0" || $port ne "0" ||
                       $ctx ne "maapi" || $proto ne "unknown")) {
            print "abort Bad extra $ip $port $ctx $proto\n";
        } else {
            if ($response eq "sendSMScode") {
                print "challenge challengeId2 U01TIENvZGUKU01T44Kz44O844OJ\n";
            } else {
                print "reject Bad response\n";
            }
        }
    } elsif ($challenge_id eq "challengeId2") {
        if ($extra && ($ip ne "0.0.0.0" || $port ne "0" ||
                       $ctx ne "maapi" || $proto ne "unknown")) {
            print "abort Bad extra $ip $port $ctx $proto\n";
        } else {
            if ($response eq "secretSMScode") {
                print "accept external admin 1000 1000 /home/admin admin\n";
            } else {
                print "reject Bad response\n";
            }
        }
    } else {
        print "reject Unknown challenge_id $challenge_id\n";
    }
}
# else exit silently

sub decode_b64 {
    my $str = shift;
    my $res = "";

    $str =~ tr|A-Za-z0-9+/||cd;             # remove non-base64 chars (padding)
    $str =~ tr|A-Za-z0-9+/| -_|;            # convert to uuencoded format
    while ($str =~ /(.{1,60})/gs) {
        my $len = chr(32 + length($1)*3/4); # compute length byte
        $res .= unpack("u", $len . $1 );    # uudecode
    }
    $res;
} 

 

Hi, Cohult:

Thank you for this example. This is very helpful. I will study it.

Thank you
sm000x

cohult
Cisco Employee
Cisco Employee

Sorry, I did not read your question properly. The example is for MFA north of NSO through the WebUI. Not MFA to devices south of NSO through NEDs.

Hi, Cohult:

Thank you for the correction. But it is still helpful for my work.

Thank you again.
sm000x

Just for completion regarding NORTHBOUD MFA. NSO now supports SSO and SAMLv2. I would claim that a better way to enable MFA northbound support is to use a SAMLv2 identity provider such as Cisco Duo and centralize your MFA needs across all your applications. More info on Duo/SAMLv2/MFA: https://duo.com/docs/sso-generic.

NSO SSO/SAMLv2 video: https://www.youtube.com/watch?v=XhoJQgTP_6A

Guide: https://developer.cisco.com/docs/nso/guides/#!single-sign-on

Hi, Rogaglia:

Thank you for the information. I will study the links. I am sure they are helpful.

THX
sm000x

rogaglia
Cisco Employee
Cisco Employee

Hi,

Support in NSO for MFA towards the devices is kind of anti-intuitive as the idea of automation is to remove any manual activities. Also, if you have a NaaS kind of setup where there is no operator involved, who should perform the MFA? The end-customer user? not clear to me,

Removing the architecture question, we could ask if it is technically possible. I think there is a possibility (did not tested myself). In NSO authgroups definition, you can can call an arbitrary action using the "callback-node" options:

                  "Invoke a standalone action to retrieve login credentials for
                  managed devices on the 'callback-node' instance.

                  The 'action-name' action is invoked on the callback node that
                  is specified by an instance identifer.";

This is well explained in the guides: https://developer.cisco.com/docs/nso/guides/#!the-nso-device-manager/authentication-groups

Inside your action, you can do what you want like interacting with a MFA system.

There is clearly a performance impact of this option that I did not analyse but you probably would need to enable commit queues.

Hi, rogaglia:

Thank you for this information.
I agree that there is performance impact. However, that is the company's direction and the company is currently asking all the network device vendors to have MFA.
I will read the "action" URL, thank you for providing this URL.

Thx
sm000x

Performance is of course one piece but remember that I was challenging the policy your company is trying to invoke because it is based on the assumption that you have an operator performing the tasks somewhere. However, in many automation scenarios, there is no operator involved. Some examples are user portals, closed-loop logics, etc. 

Hi, Rogaglia:

Thank you for this response.
I do not know much details but as far as I know, my company's MTA for automation has no operator involves.

THX
sm000x