Skip to content

Commit

Permalink
Merge pull request #90 from silinternational/develop
Browse files Browse the repository at this point in the history
Latest develop changes
  • Loading branch information
fillup authored Nov 27, 2017
2 parents 1a83333 + d5ab2de commit c01c561
Show file tree
Hide file tree
Showing 24 changed files with 791 additions and 375 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ RUN chown -R www-data:www-data \
frontend/runtime/ \
frontend/web/assets/

RUN touch /etc/default/locale

EXPOSE 80
ENTRYPOINT ["/usr/local/bin/s3-expand"]
CMD ["/data/run.sh"]
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ start: api
test:
make testunit && make testapi

testunit: composer rmTestDb upTestDb yiimigratetestDb yiimigratetestDblocal rmTestDb
testunit: composer emailcron rmTestDb upTestDb yiimigratetestDb yiimigratetestDblocal
docker-compose run emailcron whenavail emaildb 3306 100 ./yii migrate --interactive=0
docker-compose run --rm cli bash -c 'MYSQL_HOST=testDb MYSQL_DATABASE=test ./vendor/bin/codecept run unit'

# Run testunit first at least once. Otherwise, this will have 5 test failures.
testapi: upTestDb yiimigratetestDb yiimigratetestDblocal
docker-compose up -d zxcvbn
docker-compose run --rm apitest
Expand All @@ -29,6 +31,9 @@ dockerpullall:
email:
docker-compose up -d email

emailcron:
docker-compose up -d emailcron

rmDb:
docker-compose kill db
docker-compose rm -f db
Expand Down Expand Up @@ -63,4 +68,4 @@ bounce:

clean:
docker-compose kill
docker-compose rm -f
docker system prune -f
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Backend API for Identity Provider Password Management
clone at ```link coming soon```

### Additional setup for Linux & Mac
1. Add entry to ```/etc/hosts``` for ```120.0.0.1 idp-pw-api.local```
1. Add entry to ```/etc/hosts``` for ```127.0.0.1 idp-pw-api.local```
2. Run ```docker build -t idp-pw-api .```
3. Run ```make start```

Expand Down
107 changes: 66 additions & 41 deletions application/common/config/local.php.dist
Original file line number Diff line number Diff line change
@@ -1,23 +1,76 @@
<?php

use Sil\PhpEnv\Env;
use yii\helpers\ArrayHelper;

$zxcvbnApiBaseUrl = Env::get('ZXCVBN_API_BASEURL', 'http://zxcvbn:3000');

return [
'params' => [
'accessTokenHashKey' => 'KEY4TESTING',
'password' => [
'minLength' => [
'value' => 10,
'phpRegex' => '/.{10,}/',
'jsRegex' => '.{10,}',
'enabled' => true
],
'maxLength' => [
'value' => 255,
'phpRegex' => '/^.{0,255}$/',
'jsRegex' => '.{0,255}',
'enabled' => true
],
'minNum' => [
'value' => 2,
'phpRegex' => '/(\d.*){2,}/',
'jsRegex' => '(\d.*){2,}',
'enabled' => true
],
'minUpper' => [
'value' => 1,
'phpRegex' => '/([A-Z].*){1,}/',
'jsRegex' => '([A-Z].*){1,}',
'enabled' => true
],
'minSpecial' => [
'value' => 1,
'phpRegex' => '/([\W_].*){1,}/',
'jsRegex' => '([\W_].*){1,}',
'enabled' => true
],
'zxcvbn' => [
'minScore' => 2,
'enabled' => true,
'apiBaseUrl' => $zxcvbnApiBaseUrl,
]
],
],
'components' => [
'mailer' => [
'useFileTransport' => true,
'transport' => [
'host' => null,
],
],
'personnel' => [
// Example:
'class' => '\Sil\IdpPw\Common\Personnel\Insite',
'insitePeopleSearchBaseUrl' => '',
'insitePeopleSearchApiKey' => '',
'insitePeopleSearchApiSecret' => '',
],
// 'personnel' => ArrayHelper::merge(
// ['class' => 'Sil\IdpPw\Common\Personnel\IdBroker\IdBroker'],
// Env::getArrayFromPrefix('ID_BROKER_')
// ),
'auth' => [
'class' => '\Sil\IdpPw\Auth\Saml',
'signRequest' => true,
'checkResponseSigning' => true,
'requireEncryptedAssertion' => true,
'class' => Sil\IdpPw\Auth\Saml::class,
'signRequest' => false,
'checkResponseSigning' => false,
'requireEncryptedAssertion' => false,
'idpCertificate' => '',
'spCertificate' => '',
'spPrivateKey' => '',
'assertionConsumerServiceUrl' => 'http://idp-pw-api.local:8080/auth/login',
'entityId' => 'idp-pw-api.local',
'ssoUrl' => '',
'sloUrl' => '',
Expand All @@ -27,43 +80,15 @@ return [
'last_name' => ['field' => 'sn', 'element' => 0 ],
'email' => ['field' => 'mail', 'element' => 0 ],
'employee_id' => ['field' => 'gisEisPersonId', 'element' => 0],
]
],
],
'phone' => [
'class' => '\Sil\IdpPw\PhoneVerification\Nexmo\Verify',
'apiKey' => '',
'apiSecret' => '',
'class' => 'tests\mock\phone\Component',
'codeLength' => 4,
'brand' => 'Verification',
],
// 'phone' => [
// 'class' => '\Sil\IdpPw\PhoneVerification\Nexmo\Sms',
// 'apiKey' => '',
// 'apiSecret' => '',
// 'from' => '',
// ],
// 'phone' => [
// 'class' => '\Sil\IdpPw\PhoneVerification\Nexmo\VerifyThenSms',
// 'apiKey' => '',
// 'apiSecret' => '',
// 'from' => '',
// 'codeLength' => 4,
// 'brand' => 'Verification',
// ],
'passwordStore' => [
'class' => '\Sil\IdpPw\PasswordStore\Ldap',
'host' => '',
'port' => 636,
'baseDn' => '',
'adminUsername' => '',
'adminPassword' => '',
'useTls' => false,
'useSsl' => true,
'userPasswordAttribute' => 'userPassword',
'employeeIdAttribute' => 'gisEisPersonId',
'passwordLastChangeDateAttribute' => 'pwdchangedtime',
'passwordExpireDateAttribute' => 'modifytimestamp',

],
]
'passwordStore' => ArrayHelper::merge(
['class' => 'Sil\IdpPw\PasswordStore\IdBroker\IdBroker'],
Env::getArrayFromPrefix('ID_BROKER_')
),
],
];
24 changes: 15 additions & 9 deletions application/common/config/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
}
$emailServiceConfig['validIpRanges'] = Env::getArray('EMAIL_SERVICE_validIpRanges');

$mfaConfig = Env::getArrayFromPrefix('ID_BROKER_');
$mfaConfig['validIpRanges'] = Env::getArray('ID_BROKER_validIpRanges');

return [
'id' => 'app-common',
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
Expand Down Expand Up @@ -120,7 +123,9 @@
'validIpRanges' => $emailServiceConfig['validIpRanges'],
'enabled' => $emailServiceConfig['useEmailService'] && $alertsEmailEnabled,
'prefix' => function($message) use ($appEnv) {
$prefix = 'env=' . $appEnv . PHP_EOL;
$prefixData = [
'env' => $appEnv,
];

// There is no user when a console command is run
try {
Expand All @@ -129,19 +134,19 @@
$appUser = null;
}
if ($appUser && ! \Yii::$app->user->isGuest){
$prefix .= 'user='.\Yii::$app->user->identity->email . PHP_EOL;
$prefixData['user'] = \Yii::$app->user->identity->email;
}

// Try to get requested url and method
try {
$request = \Yii::$app->request;
$prefix .= 'Requested URL: ' . $request->getUrl() . PHP_EOL;
$prefix .= 'Request method: ' . $request->getMethod() . PHP_EOL;
$prefixData['url'] = $request->getUrl();
$prefixData['method'] = $request->getMethod();
} catch (\Exception $e) {
$prefix .= 'Requested URL: not available';
$prefixData['url'] = 'not available';
}

return PHP_EOL . $prefix;
return $prefixData;
},
],
[
Expand Down Expand Up @@ -247,10 +252,10 @@
'enabled' => true
],
'minNum' => [
'value' => 2,
'value' => 0,
'phpRegex' => '/(\d.*){2,}/',
'jsRegex' => '(\d.*){2,}',
'enabled' => true
'enabled' => false
],
'minUpper' => [
'value' => 0,
Expand All @@ -265,7 +270,7 @@
'enabled' => false
],
'zxcvbn' => [
'minScore' => 2,
'minScore' => 3,
'enabled' => true,
'apiBaseUrl' => $zxcvbnApiBaseUrl,
]
Expand All @@ -281,5 +286,6 @@
'url' => $supportUrl,
'feedbackUrl' => $supportFeedback,
],
'mfa' => $mfaConfig,
],
];
47 changes: 47 additions & 0 deletions application/common/models/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class Password extends Model
/** @var array */
public $config;

/** @var common\models\User **/
public $user;

public function init()
{
$this->passwordStore = \Yii::$app->passwordStore;
Expand Down Expand Up @@ -92,9 +95,53 @@ public function rules()
),
'when' => function() { return $this->config['zxcvbn']['enabled']; }
],
[
'password', 'validateNotUserAttributes',
'params'=>['first_name', 'last_name', 'idp_username', 'email'],
'skipOnError' => false,
],
];
}

public function validateNotUserAttributes($attribute, $params=null)
{
/* Ensure the password instance has a user attribute */
if (!isset($this->user)) {

/* Log error */
$log = [
'status' => 'error',
'error' => 'No User instance has been assigned to the new password. ' .
"Cannot validate it against the user's attributes.",
];
\Yii::error($log);

/* Throw exception based on exception type */
throw new ServerErrorHttpException(
\Yii::t(
'app',
'Unable to update password. Please contact support.'
),
1511195430
);
}
$userAttributeLabels = $this->user->attributeLabels();
$labelList = [];
foreach ($params as $disallowedAttribute) {
$labelList[] = $userAttributeLabels[$disallowedAttribute];
}

foreach ($params as $disallowedAttribute) {
if (mb_strpos(mb_strtolower($this->{$attribute}),
mb_strtolower($this->user->$disallowedAttribute)) !== false) {
$this->addError($attribute, sprintf(
'Your password may not contain any of these: %s (code 180)',
join(', ', $labelList)
));
}
}
}

/**
* Shortcut method to initialize a Password object
* @param string $employeeId
Expand Down
19 changes: 5 additions & 14 deletions application/common/models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -494,22 +494,12 @@ public function getPasswordMeta()
/*
* If password metadata is missing, fetch from passwordStore and update
*/
if ($this->pw_last_changed === null) {
/** @var UserPasswordMeta $pwMeta */
$pwMeta = \Yii::$app->passwordStore->getMeta($this->employee_id);

$lastChangedTimestamp = strtotime($pwMeta->passwordLastChangeDate);
$this->pw_last_changed = Utils::getDatetime($lastChangedTimestamp);
$this->pw_expires = Utils::calculatePasswordExpirationDate($this->pw_last_changed);

if ( ! $this->save()) {
throw new ServerErrorHttpException('Unable to update user record with password metadata', 1467297721);
}
}
/** @var UserPasswordMeta $pwMeta */
$pwMeta = \Yii::$app->passwordStore->getMeta($this->employee_id);

return [
'last_changed' => Utils::getIso8601($this->pw_last_changed),
'expires' => Utils::getIso8601($this->pw_expires),
'last_changed' => Utils::getIso8601($pwMeta->passwordLastChangeDate),
'expires' => Utils::getIso8601($pwMeta->passwordExpireDate),
];
}

Expand All @@ -521,6 +511,7 @@ public function getPasswordMeta()
public function setPassword($newPassword)
{
$password = Password::create($this->employee_id, $newPassword);
$password->user = $this;
$password->save();

$this->pw_last_changed = Utils::getDatetime();
Expand Down
12 changes: 7 additions & 5 deletions application/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
"yiisoft/yii2": "2.0.11.2",
"yiisoft/yii2-swiftmailer": "*",
"yiisoft/yii2-gii": "*",
"silinternational/email-service-php-client": "^2.0.0",
"silinternational/php-env": "^2.1.0",
"silinternational/email-service-php-client": "^2.0.1",
"silinternational/php-env": "^2.1.1",
"silinternational/yii2-json-log-targets": "^1.0.0",
"silinternational/yii2-email-log-target": "^1.0.1",
"silinternational/idp-pw-api-common": "^1.0",
"silinternational/idp-pw-api-personnel-insite": "^2.0.1",
"silinternational/idp-pw-api-personnel-id-broker": "^1.0.1",
"silinternational/idp-pw-api-personnel-id-broker": "^1.2.1",
"silinternational/idp-pw-api-personnel-multiple": "^1.0.0",
"silinternational/idp-pw-api-auth-saml": "^1.0.1",
"silinternational/idp-pw-api-passwordstore-ldap": "^2.0",
"silinternational/idp-pw-api-passwordstore-id-broker": "^2.0",
"silinternational/idp-pw-api-passwordstore-ldap": "^2.1",
"silinternational/idp-pw-api-passwordstore-id-broker": "^3.2.0",
"silinternational/idp-pw-api-passwordstore-multiple": "^1.0.1",
"silinternational/idp-pw-api-phoneverification-nexmo": "^2.0",
"silinternational/zxcvbn-api-client-php": "^2.0",
"google/recaptcha": "^1.1.2",
Expand Down
Loading

0 comments on commit c01c561

Please sign in to comment.