From 038d24eff0ec33855f2d78a3b498ba67431f5d6a Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 7 Sep 2017 13:58:10 +0200 Subject: [PATCH 01/63] License headers --- .../AclEventsCleanPermissionCacheListener.java | 15 +++++++++++++++ ...ershipEventsCleanPermissionCacheListener.java | 15 +++++++++++++++ .../UserEventsCleanPermissionCacheListener.java | 15 +++++++++++++++ .../voms/admin/operations/CurrentAdmin.java | 16 +++++++++------- .../ImplicitNamingStrategy32Legacy.java | 15 +++++++++++++++ .../util/migration/AbstractSocketFactory.java | 15 +++++++++++++++ .../util/migration/CANLAxisSocketFactory.java | 16 +++++++++------- .../migration/CSRFVOMSACLServiceLocator.java | 15 +++++++++++++++ .../migration/CSRFVOMSAdminServiceLocator.java | 15 +++++++++++++++ .../CSRFVOMSAttributesServiceLocator.java | 15 +++++++++++++++ .../util/migration/HttpClientSocketFactory.java | 15 +++++++++++++++ .../voms/admin/util/migration/MigrateVo.java | 16 +++++++++------- .../actions/apiv2/ImportAupVersionsAction.java | 16 +++++++++------- 13 files changed, 171 insertions(+), 28 deletions(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/AclEventsCleanPermissionCacheListener.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/AclEventsCleanPermissionCacheListener.java index 31ff280a..3b86c34d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/AclEventsCleanPermissionCacheListener.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/AclEventsCleanPermissionCacheListener.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.event.permission_cache; import java.util.EnumSet; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/MembershipEventsCleanPermissionCacheListener.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/MembershipEventsCleanPermissionCacheListener.java index 24ab61c0..84461740 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/MembershipEventsCleanPermissionCacheListener.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/MembershipEventsCleanPermissionCacheListener.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.event.permission_cache; import java.util.EnumSet; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/UserEventsCleanPermissionCacheListener.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/UserEventsCleanPermissionCacheListener.java index 58d947dd..6cde8059 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/UserEventsCleanPermissionCacheListener.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/permission_cache/UserEventsCleanPermissionCacheListener.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.event.permission_cache; import java.util.EnumSet; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/CurrentAdmin.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/CurrentAdmin.java index 3220a192..4c2cbbcb 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/CurrentAdmin.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/CurrentAdmin.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.operations; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/ImplicitNamingStrategy32Legacy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/ImplicitNamingStrategy32Legacy.java index c678f5a4..03bd6924 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/ImplicitNamingStrategy32Legacy.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/ImplicitNamingStrategy32Legacy.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.persistence; import java.util.List; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/AbstractSocketFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/AbstractSocketFactory.java index 17890346..345fe21b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/AbstractSocketFactory.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/AbstractSocketFactory.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.util.migration; import java.io.FileInputStream; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CANLAxisSocketFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CANLAxisSocketFactory.java index b5a81496..c7aa5430 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CANLAxisSocketFactory.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CANLAxisSocketFactory.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.util.migration; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSACLServiceLocator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSACLServiceLocator.java index bd5e9213..1c691797 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSACLServiceLocator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSACLServiceLocator.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.util.migration; import javax.xml.rpc.Call; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAdminServiceLocator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAdminServiceLocator.java index 8be4ce49..29f91d85 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAdminServiceLocator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAdminServiceLocator.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.util.migration; import javax.xml.rpc.Call; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAttributesServiceLocator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAttributesServiceLocator.java index 1b4c2346..e063d6d9 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAttributesServiceLocator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/CSRFVOMSAttributesServiceLocator.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.util.migration; import javax.xml.rpc.Call; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/HttpClientSocketFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/HttpClientSocketFactory.java index 45c4cbce..f529d893 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/HttpClientSocketFactory.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/HttpClientSocketFactory.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.util.migration; import java.io.IOException; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java index 1fcf4c3f..38cebc8e 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.util.migration; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/ImportAupVersionsAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/ImportAupVersionsAction.java index d295ad27..4861376c 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/ImportAupVersionsAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/ImportAupVersionsAction.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.view.actions.apiv2; From 4c5b83ac6cbc5e8d271e82da31f4046f9aa59cc1 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 14:19:05 +0100 Subject: [PATCH 02/63] pom: bump version to 3.7.1-SNAPSHOT --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 4 ++-- voms-container/pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 1971c9a5..ff611ef4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.7.0 + 3.7.1-SNAPSHOT pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index 54391611..d000a0d5 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.7.0 + 3.7.1-SNAPSHOT voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 39f2b017..9686199e 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -24,7 +24,7 @@ org.italiangrid voms-admin-parent - 3.7.0 + 3.7.1-SNAPSHOT voms-admin-server @@ -36,7 +36,7 @@ ${project.version} 2.0.2 - 2.3.32 + 2.3.34 2.0.1 3.7.1 5.2.8.Final diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 4d35c4f8..23055ce7 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.7.0 + 3.7.1-SNAPSHOT voms-container From cd2fbcfb196e4d1f7c3463395e5a779951878a62 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 14:22:14 +0100 Subject: [PATCH 03/63] compose: minor changes --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 25eb4a0e..7513165c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,7 +40,7 @@ services: - ~/git/voms-admin-server/docker/voms-admin-server/setup:/scripts:ro - ~/git/orgdb-fake-users/:/orgdb-fake-users:ro - ~/git/voms-migrate:/migrate:ro - # - ~/orgdb:/orgdb:ro + # - ~/orgdb:/orgdb:ro ports: # 20001 is the default yourkit port @@ -79,7 +79,7 @@ services: # VOMS_SKIP_CONFIGURE: y VOMS_UPGRADE_DB: y - # VOMS_LOAD_DB_DUMP: y + #VOMS_LOAD_DB_DUMP: y VOMS_DEV_MODE: y VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check From 32b6584849f02cba63e4148619e454e8af43b734 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 18:31:42 +0100 Subject: [PATCH 04/63] pom: bump https-utils version to 0.4.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ff611ef4..a5496c87 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 2.0.5-beta 1.6.6 1.0.6 - 0.3.6 + 0.4.0 1.2.1 1.4 From ff9ff0e6c24fa3bdc31e1b2f5efa97bc67aab811 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 18:32:05 +0100 Subject: [PATCH 05/63] docker: extend italiangrid/base-dev:latest --- docker/voms-admin-server/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/voms-admin-server/Dockerfile b/docker/voms-admin-server/Dockerfile index d86bd69f..76b21fd0 100644 --- a/docker/voms-admin-server/Dockerfile +++ b/docker/voms-admin-server/Dockerfile @@ -1,4 +1,4 @@ -FROM italiangrid/base-dev +FROM italiangrid/base-dev:latest RUN sed -i 's/socket_timeout=3/socket_timeout=1/' /etc/yum/pluginconf.d/fastestmirror.conf && \ echo "include_only=.garr.it,.cern.ch" >> /etc/yum/pluginconf.d/fastestmirror.conf && \ From 71883a8df4855ecaeafeeaea500d6e206ac4f3be Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 18:32:31 +0100 Subject: [PATCH 06/63] compose: docker for Mac configuration which works fine also for docker in general --- docker-compose.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7513165c..29eb5fc5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -146,12 +146,13 @@ services: environment: - MODE=tcp - - DOCKER_TLS_VERIFY - - DOCKER_HOST - - DOCKER_CERT_PATH + # - DOCKER_TLS_VERIFY + # - DOCKER_HOST + # - DOCKER_CERT_PATH volumes: - - $DOCKER_CERT_PATH:$DOCKER_CERT_PATH + # - $DOCKER_CERT_PATH:$DOCKER_CERT_PATH + - /var/run/docker.sock:/var/run/docker.sock links: - adminserver From 6969682c36b62ed31e1c9d07bd72a71f0f5be38c Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 30 Nov 2017 18:35:39 +0100 Subject: [PATCH 07/63] travis: add travis build config --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..4d11746e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: java +dist: trusty +sudo: required +services: + - docker +jdk: + - openjdk8 +script: + - mvn clean package +cache: + directories: + - "$HOME/.m2/repository" From d64d6ae963f7980c970cc03126d588feacd8175d Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 1 Dec 2017 11:15:56 +0100 Subject: [PATCH 08/63] pom: axis 1.2.1 -> 1.4 it's about time... --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a5496c87..dc424e63 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 1.6.6 1.0.6 0.4.0 - 1.2.1 + 1.4 1.4 1.4 From d1459dabe069bbc22825734220546dbf2372263e Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 1 Dec 2017 11:21:10 +0100 Subject: [PATCH 09/63] doc: travis build status badge in README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9172e55f..6d51b630 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # VOMS Admin server +[![Build Status](https://travis-ci.org/italiangrid/voms-admin-server.svg?branch=develop)](https://travis-ci.org/italiangrid/voms-admin-server) + The Virtual Organization Membership Service is a Grid attribute authority which serves as central repository for VO user authorization information, providing support for sorting users into group hierarchies, keeping track of their roles From 58d97425da97ef01f7b8137879a198c16a7ec557 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 6 Dec 2017 10:24:46 +0100 Subject: [PATCH 10/63] docker: changes to voms-admin-server test image --- docker/voms-admin-server/Dockerfile | 2 +- docker/voms-admin-server/setup/configure-vos.sh | 6 ++++-- docker/voms-admin-server/setup/create-schemas.sh | 4 +++- docker/voms-admin-server/setup/run.sh | 6 ++++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docker/voms-admin-server/Dockerfile b/docker/voms-admin-server/Dockerfile index 76b21fd0..925f8db6 100644 --- a/docker/voms-admin-server/Dockerfile +++ b/docker/voms-admin-server/Dockerfile @@ -6,7 +6,7 @@ RUN sed -i 's/socket_timeout=3/socket_timeout=1/' /etc/yum/pluginconf.d/fastestm ADD setup /scripts -RUN yum -y -d2 install sudo && sh /scripts/setup-voms-user.sh +RUN yum -y install sudo && sh /scripts/setup-voms-user.sh RUN chmod 755 "/scripts/run.sh" RUN cp /scripts/emi-oracle-11.repo /etc/yum.repos.d && \ diff --git a/docker/voms-admin-server/setup/configure-vos.sh b/docker/voms-admin-server/setup/configure-vos.sh index ccd48701..4b8914ab 100644 --- a/docker/voms-admin-server/setup/configure-vos.sh +++ b/docker/voms-admin-server/setup/configure-vos.sh @@ -3,6 +3,8 @@ set -ex VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} VO_COUNT=${VOMS_VO_COUNT:-1} +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} +VOMS_SMTP_HOST=${VOMS_SMTP_HOST:-mail} BASE_CORE_PORT=${VOMS_BASE_CORE_PORT:-15000} configure_vo(){ @@ -15,9 +17,9 @@ configure_vo(){ --dbname ${VO_NAME} \ --dbusername $VOMS_DB_USERNAME \ --dbpassword $VOMS_DB_PASSWORD \ - --dbhost db \ + --dbhost ${VOMS_MYSQL_HOST} \ --mail-from $VOMS_MAIL_FROM \ - --smtp-host mail \ + --smtp-host ${VOMS_SMTP_HOST} \ --membership-check-period 60 \ --hostname ${VOMS_HOSTNAME} \ --core-port $((${BASE_CORE_PORT}+$1)) \ diff --git a/docker/voms-admin-server/setup/create-schemas.sh b/docker/voms-admin-server/setup/create-schemas.sh index 173b14e7..06c3e173 100644 --- a/docker/voms-admin-server/setup/create-schemas.sh +++ b/docker/voms-admin-server/setup/create-schemas.sh @@ -1,6 +1,8 @@ #!/bin/bash set -x +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} + VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} VO_COUNT=${VOMS_VO_COUNT:-1} @@ -14,7 +16,7 @@ create_vo_schema(){ EOF cat ${tmp_file} - cat ${tmp_file} | mysql -hdb -uroot -p${MYSQL_ROOT_PASSWORD} + cat ${tmp_file} | mysql -h${VOMS_MYSQL_HOST} -uroot -p${MYSQL_ROOT_PASSWORD} } diff --git a/docker/voms-admin-server/setup/run.sh b/docker/voms-admin-server/setup/run.sh index 6afad0b5..e629e6e1 100755 --- a/docker/voms-admin-server/setup/run.sh +++ b/docker/voms-admin-server/setup/run.sh @@ -6,10 +6,12 @@ VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} VO_COUNT=${VOMS_VO_COUNT:-1} VOMS_BASE_CORE_PORT=${VOMS_BASE_CORE_PORT:-15000} +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} +VOMS_MYSQL_PORT=${VOMS_MYSQL_PORT:-3306} # Wait for database service to be up -mysql_host=db -mysql_port=3306 +mysql_host=${VOMS_MYSQL_HOST} +mysql_port=${VOMS_MYSQL_PORT} echo -n "waiting for TCP connection to $mysql_host:$mysql_port..." From 53993595cdb79c6516a3165bf2c13695494d00d8 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 6 Dec 2017 10:55:41 +0100 Subject: [PATCH 11/63] docker: do not harcode host cert path --- docker/voms-admin-server/setup/run.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docker/voms-admin-server/setup/run.sh b/docker/voms-admin-server/setup/run.sh index e629e6e1..d1c95a2d 100755 --- a/docker/voms-admin-server/setup/run.sh +++ b/docker/voms-admin-server/setup/run.sh @@ -15,6 +15,7 @@ mysql_port=${VOMS_MYSQL_PORT} echo -n "waiting for TCP connection to $mysql_host:$mysql_port..." + while ! nc -w 1 $mysql_host $mysql_port 2>/dev/null do echo -n . @@ -47,8 +48,11 @@ cp ${SCRIPTS_PREFIX}/tnsnames.ora /home/voms chown voms:voms /home/voms/tnsnames.ora ## Setup certificates -cp /etc/grid-security/hostcert.pem /etc/grid-security/vomscert.pem -cp /etc/grid-security/hostkey.pem /etc/grid-security/vomskey.pem +VOMS_X509_CERT=${VOMS_X509_CERT:-/etc/grid-security/hostcert.pem} +VOMS_X509_KEY=${VOMS_X509_KEY:-/etc/grid-security/hostkey.pem} + +cp ${VOMS_X509_CERT} /etc/grid-security/vomscert.pem +cp ${VOMS_X509_KEY} /etc/grid-security/vomskey.pem chown voms:voms /etc/grid-security/voms*.pem # Do this or voms-admin webapp will fail silently and always return 503 From bab2da98962eabf465e9fcbaeaca2c74e3f7c28c Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 26 Jan 2018 18:26:31 +0100 Subject: [PATCH 12/63] repo: move repos to repo.cloud.cnaf.infn.it --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dc424e63..2506a616 100644 --- a/pom.xml +++ b/pom.xml @@ -237,13 +237,13 @@ cnaf-releases CNAF releases - http://radiohead.cnaf.infn.it:8081/nexus/content/repositories/cnaf-releases/ + https://repo.cloud.cnaf.infn.it/repository/cnaf-releases/ cnaf-snapshots CNAF snapshots - http://radiohead.cnaf.infn.it:8081/nexus/content/repositories/cnaf-snapshots/ + https://repo.cloud.cnaf.infn.it/repository/cnaf-snapshots/ From 30609423966e8ea4a48fa0595b9306cd70c2325e Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 29 Mar 2018 15:02:09 +0200 Subject: [PATCH 13/63] Fix conversion error that breaks audit log search --- .../security/voms/admin/view/actions/audit/IndexAction.java | 4 +++- .../actions/audit/AuditLogSearchParams-conversion.properties | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/IndexAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/IndexAction.java index 2043baaf..a07a343f 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/IndexAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/IndexAction.java @@ -32,7 +32,9 @@ import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.Preparable; -@Results({ @Result(name = BaseAction.SUCCESS, location = "auditLog") }) +@Results({ @Result(name = BaseAction.SUCCESS, location = "auditLog"), + @Result(name = BaseAction.INPUT, location = "auditLog") +}) public class IndexAction extends BaseAction implements ModelDriven, Preparable { diff --git a/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties new file mode 100644 index 00000000..55318c43 --- /dev/null +++ b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties @@ -0,0 +1,2 @@ +fromTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter +toTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter From d0433e15a06bd6b69e03327dc9b0f6dba352a182 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 8 May 2018 18:43:50 +0200 Subject: [PATCH 14/63] docker: compose & images changes --- docker-compose.yml | 1 + docker/prod/Dockerfile | 6 ++++++ docker/prod/build-image.sh | 5 +++++ docker/voms-admin-server/build-image.sh | 2 +- docker/voms-admin-server/push-image.sh | 6 +++--- 5 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 docker/prod/Dockerfile create mode 100755 docker/prod/build-image.sh diff --git a/docker-compose.yml b/docker-compose.yml index 29eb5fc5..71179791 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,7 @@ version: '2' services: + data: image: busybox volumes: diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile new file mode 100644 index 00000000..f1570d8e --- /dev/null +++ b/docker/prod/Dockerfile @@ -0,0 +1,6 @@ +FROM java:8 + +VOLUME /etc/voms-admin +VOLUME /var/log/voms-admin + +EXPOSE 8443 1044 diff --git a/docker/prod/build-image.sh b/docker/prod/build-image.sh new file mode 100755 index 00000000..6e9c8ec8 --- /dev/null +++ b/docker/prod/build-image.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-server"} + +docker build --no-cache=true -t ${VOMS_ADMIN_SERVER_IMAGE} . diff --git a/docker/voms-admin-server/build-image.sh b/docker/voms-admin-server/build-image.sh index 6e9c8ec8..551d5aa0 100755 --- a/docker/voms-admin-server/build-image.sh +++ b/docker/voms-admin-server/build-image.sh @@ -1,5 +1,5 @@ #!/bin/bash -VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-server"} +VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-server-dev"} docker build --no-cache=true -t ${VOMS_ADMIN_SERVER_IMAGE} . diff --git a/docker/voms-admin-server/push-image.sh b/docker/voms-admin-server/push-image.sh index 75b158e4..bea534b0 100755 --- a/docker/voms-admin-server/push-image.sh +++ b/docker/voms-admin-server/push-image.sh @@ -7,9 +7,9 @@ VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-serve DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd ${DIR} -if [ -n ${DOCKER_REGISTRY_HOST} ]; then +if [ -z ${DOCKER_REGISTRY_HOST} ]; then + docker push ${VOMS_ADMIN_SERVER_IMAGE} +else docker tag ${VOMS_ADMIN_SERVER_IMAGE} ${DOCKER_REGISTRY_HOST}/${VOMS_ADMIN_SERVER_IMAGE} docker push ${DOCKER_REGISTRY_HOST}/${VOMS_ADMIN_SERVER_IMAGE} -else - docker push ${VOMS_ADMIN_SERVER_IMAGE} fi From 40754f212b6d46e0d60b8e45b6931b4a470d8d62 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 8 May 2018 18:44:21 +0200 Subject: [PATCH 15/63] pom: add hamcrest deps --- pom.xml | 14 ++++++++++++++ voms-admin-server/pom.xml | 14 +++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2506a616..8b056bd4 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ UTF-8 4.11 + 1.3 2.0.5-beta 1.6.6 1.0.6 @@ -61,6 +62,19 @@ ${junit.version} + + org.hamcrest + hamcrest-core + ${hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${hamcrest.version} + test + + org.mockito mockito-core diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 9686199e..a8d16c09 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -186,6 +186,18 @@ junit + + org.hamcrest + hamcrest-core + test + + + + org.hamcrest + hamcrest-library + test + + org.mockito mockito-core @@ -223,7 +235,7 @@ guava provided - + com.mchange c3p0 From 3f1835b7271216b9b70f6f141438f8638e8d4923 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 8 May 2018 18:44:49 +0200 Subject: [PATCH 16/63] test: add french ca trust anchors --- .../test/resources/trust-anchors/16054abd.0 | 28 ++++++++++++++++ .../trust-anchors/16054abd.namespaces | 28 ++++++++++++++++ .../trust-anchors/16054abd.signing_policy | 5 +++ .../test/resources/trust-anchors/72aa436d.0 | 33 +++++++++++++++++++ .../trust-anchors/72aa436d.signing_policy | 5 +++ .../test/resources/trust-anchors/7ca9677b.0 | 28 ++++++++++++++++ .../trust-anchors/7ca9677b.namespaces | 28 ++++++++++++++++ .../trust-anchors/7ca9677b.signing_policy | 5 +++ .../test/resources/trust-anchors/80df9b28.0 | 33 +++++++++++++++++++ .../trust-anchors/80df9b28.signing_policy | 5 +++ .../AC-GRID-FR-Personnels.crl_url | 1 + .../trust-anchors/AC-GRID-FR-Personnels.info | 11 +++++++ .../trust-anchors/AC-GRID-FR-Personnels.pem | 33 +++++++++++++++++++ .../AC-GRID-FR-Personnels.signing_policy | 5 +++ .../trust-anchors/AC-GRID-FR.crl_url | 1 + .../resources/trust-anchors/AC-GRID-FR.info | 11 +++++++ .../trust-anchors/AC-GRID-FR.namespaces | 28 ++++++++++++++++ .../resources/trust-anchors/AC-GRID-FR.pem | 28 ++++++++++++++++ .../trust-anchors/AC-GRID-FR.signing_policy | 5 +++ 19 files changed, 321 insertions(+) create mode 100644 voms-admin-server/src/test/resources/trust-anchors/16054abd.0 create mode 100644 voms-admin-server/src/test/resources/trust-anchors/16054abd.namespaces create mode 100644 voms-admin-server/src/test/resources/trust-anchors/16054abd.signing_policy create mode 100644 voms-admin-server/src/test/resources/trust-anchors/72aa436d.0 create mode 100644 voms-admin-server/src/test/resources/trust-anchors/72aa436d.signing_policy create mode 100644 voms-admin-server/src/test/resources/trust-anchors/7ca9677b.0 create mode 100644 voms-admin-server/src/test/resources/trust-anchors/7ca9677b.namespaces create mode 100644 voms-admin-server/src/test/resources/trust-anchors/7ca9677b.signing_policy create mode 100644 voms-admin-server/src/test/resources/trust-anchors/80df9b28.0 create mode 100644 voms-admin-server/src/test/resources/trust-anchors/80df9b28.signing_policy create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.crl_url create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.info create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.pem create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.signing_policy create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.crl_url create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.info create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.namespaces create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.pem create mode 100644 voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.signing_policy diff --git a/voms-admin-server/src/test/resources/trust-anchors/16054abd.0 b/voms-admin-server/src/test/resources/trust-anchors/16054abd.0 new file mode 100644 index 00000000..87639813 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/16054abd.0 @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzjCCAzagAwIBAgISESHcZGpjVbhv3LcwHBxmFWKhMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBFMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMRMwEQYDVQQDDApBQyBHUklELUZSMIIBojANBgkqhkiG9w0BAQEF +AAOCAY8AMIIBigKCAYEAywcrhCkF87S7e/Sfc0S+QGS4ED9EuYvoQj8KiWlyz9UF +nccNtjaxnlJbaGU6myNreeEEbt+QdydQ/vkPQd2gEhoxirz6VDJgRg2i56Zw/JL9 +FVcmDgKG6t7Ap9/NB3MobXWPd7yQu7SIfnd3BnLW87tOdILpiODZNOWeh6Qg1Fgn +aFHRjVPN6ugU1qbW44sPDv0yFhNRfnsDomVOewRg46fxv8tah+lIYsVulGYVhmkI +AgNs9YMTclukxPL5YOFgeY+3A+G/1NwKmteFqBIQRcaF1UbHrSsn6H5cIdsEJ1NT +IBPYuDGD/SkH5dFpOeyZ+RLxCaoI4W+dVyYhVealdrtmI2XQL7lLWLTHJzZqRBcA +gc60J2bjZl3HwxFE/QKW5f67zLkupFPO61OWeAl+pwIIE4Xo6z0ubNrLg5MqiO7G +7YOPocSlkBMIv+OzhrzMxsZpjSaLm32/nGyj0T+XQwUN4gK87VkHa0lz+qU6TTG0 +bggGOK72rcXdGZWlzGfzAgMBAAGjgbcwgbQwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wUQYDVR0gBEowSDBGBgRVHSAAMD4wPAYIKwYBBQUHAgEWMGh0 +dHA6Ly9ncmlkLWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvcGMtZ3JpZC1mcjAd +BgNVHQ4EFgQUqgzWvPnZZT1wilEwII9M/s1gueMwHwYDVR0jBBgwFoAUqgzWvPnZ +ZT1wilEwII9M/s1gueMwDQYJKoZIhvcNAQELBQADggGBAIGprfsrGbphQnPMyshh +SOB+Q/hLV3vSyT52kSuifHMHkoLA61cJT/Lrp5Vb2yKi7SWzbWrCD4dNsbTAt838 +7WZUVeSkvvqJmDeMI/Jj4LVMVSnLsxFHwrphw1KiEen2kZL8BmbTRW1x3UnuF7Dx +Evr/Um7O+gZFg0SHCVCeCpYYROLZOFre98lvvYRn2vixKPSXxDkfaeW4B91SD3is +qMW8ATtq3Wp5ZOGRlMzCEEt2OmLnSYldkjb/I1Noi3A9Uzwuxxm9vDfG291uI6ks +wMpYrwVXjoUZWZ1FSf766SBtAzLPYjcpmJwRvTIxNyMWedZCMbkKhRL9z1ZhEMbR +chLvh3mnrDdFbUoCCQ4ZqmcgYIgw3+JzIf3vRszPpJirJ0ZoZKrBs4QRDdlFZtON +kBA7U1h+lAzYSExpZPoF8m7meKtL9oanlJ66XLGv0yg6N7oL1mvPkR/QiLSrOeRI ++yS8kr+zh4fpr9gRJUQkxA+xGSiGUk9DZwK0TA/3WICj7w== +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/16054abd.namespaces b/voms-admin-server/src/test/resources/trust-anchors/16054abd.namespaces new file mode 100644 index 00000000..7f3211f7 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/16054abd.namespaces @@ -0,0 +1,28 @@ +############################################################################## +#NAMESPACES-VERSION: 1.0 +# +# @(#)AC-GRID-FR.signing_policy.namespaces +# CA alias : AC-GRID-FR +# subord_of: +# subjectDN: /C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR +# hash : AC-GRID-FR.signing_policy +# (generated automatically from AC-GRID-FR.signing_policy) +# +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" \ + PERMIT Subject "/O=GRID-FR/.*" + diff --git a/voms-admin-server/src/test/resources/trust-anchors/16054abd.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/16054abd.signing_policy new file mode 100644 index 00000000..1ae6cbd1 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/16054abd.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services"' diff --git a/voms-admin-server/src/test/resources/trust-anchors/72aa436d.0 b/voms-admin-server/src/test/resources/trust-anchors/72aa436d.0 new file mode 100644 index 00000000..3bae8f59 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/72aa436d.0 @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCBCqgAwIBAgISESEbWlKSHT/Bwe1tXK8w0TWHMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBQMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMR4wHAYDVQQDDBVBQyBHUklELUZSIFBlcnNvbm5lbHMwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDWvrNF8vQ5jpSvmXPzEhBp958C43rp +DMTcQWWd0A78t1aKizc+gNAso2KQivjt1Yu/KiMSjpi85LEOKOB3OESUY6c+slfV +L5psH5bwif6zu5guiLFtd/XmRGC4wFHh1Zo8NTply0NlzaN9/bY+BQnlstexbiGe +Mm3W7AfzNmmszykgIegoOmAlk1P2Snxbk5kCO/uQlezQzNLUFB5OYE/DL4gOpONE +Xa470fCCToSUrJ2HlteU0il/8tSgBws2xENUzA/r/ZmwG6IeVHYxukK4SzOn8fFU +sLoNE0srlDz8Xgdr9XZyEFdQXJ4IsWGgGLyKsnN/jwPsZ7qkhvaDbKdml7i1S5F9 +PZf1hSgwRgx2C4NP4JZacWiG+UNTk1XM0ZiIUTjhMN+isqOHiUKRBXyg9gLw01RP +mOrA8xjzt2VjkobSdgA/9R7p+sdYTWCMsgAaPd2P5ZO1XrvRCkfUk5jKSw5zPcdz +OAj84VwO4p1cGAguc5vvH3+0b62NpUlbNCECAwEAAaOCAZ8wggGbMA4GA1UdDwEB +/wQEAwIBBjBRBgNVHSAESjBIMEYGBFUdIAAwPjA8BggrBgEFBQcCARYwaHR0cDov +L2dyaWQtZnIucG5jbi5lZHVjYXRpb24uZ291di5mci9wYy1ncmlkLWZyMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5ncmlk +LWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvYWMtZ3JpZC1mci5jcmwwgZYGCCsG +AQUFBwEBBIGJMIGGMEQGCCsGAQUFBzAChjhodHRwOi8vY2VyLmdyaWQtZnIucG5j +bi5lZHVjYXRpb24uZ291di5mci9hYy1ncmlkLWZyLmNlcjA+BggrBgEFBQcwAYYy +aHR0cDovL29jc3AuZ3JpZC1mci5wbmNuLmVkdWNhdGlvbi5nb3V2LmZyL2dyaWQt +ZnIwHQYDVR0OBBYEFN49xvEGIjeZn88iCJUA5wHioLwQMB8GA1UdIwQYMBaAFKoM +1rz52WU9cIpRMCCPTP7NYLnjMA0GCSqGSIb3DQEBCwUAA4IBgQBxa53DK6bHVXcv +5Uo+QIgpi43ybbXlSY/7a2fFiMZLRiJ/gpm9qicZUAfNbXIG8eY7i6SCIIFa/on4 +0CnZjPeFy7Hi4HZwFpT4Mdu6G5yAV94k70sWqi5Vfdcv0PO37GI0QyxqtzTCB07n +JhhE/uyYuwLryXXOUq/r4z2O1N4OZyeALiA/ojO0oQxzuULoveFyasd05tmmPD+r +TEePaoly889oH61GbOvYx7syO2AoViVGa2kZX5qUqfVhiYa3vd1uhU8UGqs8iHWW +f8BaCawV7GpJ8yx4+rlLHT5nzLcrg8+c8tGHuoFLgPdS3WuJXNrQjtwfd95u/Rx0 +mQUm5QDZgIdYSJmYYt6fVyqxRrszSOcS/6qsVeethyqP0ni5jsQjxiWz1jb2cfiT +Er1nrK8Z3F4wm+pLovR5em7ck1BayNUmcXonsfHcUZVb/skfLxxVu7znPI8epMz+ +5EgHvw2trURiay3DlgXy6uj5tp/PbG6V+UtgH5Iso9WzByLXcuk= +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/72aa436d.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/72aa436d.signing_policy new file mode 100644 index 00000000..a0d33932 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/72aa436d.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR-Personnels.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/O=GRID-FR/*"' diff --git a/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.0 b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.0 new file mode 100644 index 00000000..87639813 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.0 @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzjCCAzagAwIBAgISESHcZGpjVbhv3LcwHBxmFWKhMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBFMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMRMwEQYDVQQDDApBQyBHUklELUZSMIIBojANBgkqhkiG9w0BAQEF +AAOCAY8AMIIBigKCAYEAywcrhCkF87S7e/Sfc0S+QGS4ED9EuYvoQj8KiWlyz9UF +nccNtjaxnlJbaGU6myNreeEEbt+QdydQ/vkPQd2gEhoxirz6VDJgRg2i56Zw/JL9 +FVcmDgKG6t7Ap9/NB3MobXWPd7yQu7SIfnd3BnLW87tOdILpiODZNOWeh6Qg1Fgn +aFHRjVPN6ugU1qbW44sPDv0yFhNRfnsDomVOewRg46fxv8tah+lIYsVulGYVhmkI +AgNs9YMTclukxPL5YOFgeY+3A+G/1NwKmteFqBIQRcaF1UbHrSsn6H5cIdsEJ1NT +IBPYuDGD/SkH5dFpOeyZ+RLxCaoI4W+dVyYhVealdrtmI2XQL7lLWLTHJzZqRBcA +gc60J2bjZl3HwxFE/QKW5f67zLkupFPO61OWeAl+pwIIE4Xo6z0ubNrLg5MqiO7G +7YOPocSlkBMIv+OzhrzMxsZpjSaLm32/nGyj0T+XQwUN4gK87VkHa0lz+qU6TTG0 +bggGOK72rcXdGZWlzGfzAgMBAAGjgbcwgbQwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wUQYDVR0gBEowSDBGBgRVHSAAMD4wPAYIKwYBBQUHAgEWMGh0 +dHA6Ly9ncmlkLWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvcGMtZ3JpZC1mcjAd +BgNVHQ4EFgQUqgzWvPnZZT1wilEwII9M/s1gueMwHwYDVR0jBBgwFoAUqgzWvPnZ +ZT1wilEwII9M/s1gueMwDQYJKoZIhvcNAQELBQADggGBAIGprfsrGbphQnPMyshh +SOB+Q/hLV3vSyT52kSuifHMHkoLA61cJT/Lrp5Vb2yKi7SWzbWrCD4dNsbTAt838 +7WZUVeSkvvqJmDeMI/Jj4LVMVSnLsxFHwrphw1KiEen2kZL8BmbTRW1x3UnuF7Dx +Evr/Um7O+gZFg0SHCVCeCpYYROLZOFre98lvvYRn2vixKPSXxDkfaeW4B91SD3is +qMW8ATtq3Wp5ZOGRlMzCEEt2OmLnSYldkjb/I1Noi3A9Uzwuxxm9vDfG291uI6ks +wMpYrwVXjoUZWZ1FSf766SBtAzLPYjcpmJwRvTIxNyMWedZCMbkKhRL9z1ZhEMbR +chLvh3mnrDdFbUoCCQ4ZqmcgYIgw3+JzIf3vRszPpJirJ0ZoZKrBs4QRDdlFZtON +kBA7U1h+lAzYSExpZPoF8m7meKtL9oanlJ66XLGv0yg6N7oL1mvPkR/QiLSrOeRI ++yS8kr+zh4fpr9gRJUQkxA+xGSiGUk9DZwK0TA/3WICj7w== +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.namespaces b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.namespaces new file mode 100644 index 00000000..7f3211f7 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.namespaces @@ -0,0 +1,28 @@ +############################################################################## +#NAMESPACES-VERSION: 1.0 +# +# @(#)AC-GRID-FR.signing_policy.namespaces +# CA alias : AC-GRID-FR +# subord_of: +# subjectDN: /C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR +# hash : AC-GRID-FR.signing_policy +# (generated automatically from AC-GRID-FR.signing_policy) +# +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" \ + PERMIT Subject "/O=GRID-FR/.*" + diff --git a/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.signing_policy new file mode 100644 index 00000000..1ae6cbd1 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/7ca9677b.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services"' diff --git a/voms-admin-server/src/test/resources/trust-anchors/80df9b28.0 b/voms-admin-server/src/test/resources/trust-anchors/80df9b28.0 new file mode 100644 index 00000000..3bae8f59 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/80df9b28.0 @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCBCqgAwIBAgISESEbWlKSHT/Bwe1tXK8w0TWHMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBQMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMR4wHAYDVQQDDBVBQyBHUklELUZSIFBlcnNvbm5lbHMwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDWvrNF8vQ5jpSvmXPzEhBp958C43rp +DMTcQWWd0A78t1aKizc+gNAso2KQivjt1Yu/KiMSjpi85LEOKOB3OESUY6c+slfV +L5psH5bwif6zu5guiLFtd/XmRGC4wFHh1Zo8NTply0NlzaN9/bY+BQnlstexbiGe +Mm3W7AfzNmmszykgIegoOmAlk1P2Snxbk5kCO/uQlezQzNLUFB5OYE/DL4gOpONE +Xa470fCCToSUrJ2HlteU0il/8tSgBws2xENUzA/r/ZmwG6IeVHYxukK4SzOn8fFU +sLoNE0srlDz8Xgdr9XZyEFdQXJ4IsWGgGLyKsnN/jwPsZ7qkhvaDbKdml7i1S5F9 +PZf1hSgwRgx2C4NP4JZacWiG+UNTk1XM0ZiIUTjhMN+isqOHiUKRBXyg9gLw01RP +mOrA8xjzt2VjkobSdgA/9R7p+sdYTWCMsgAaPd2P5ZO1XrvRCkfUk5jKSw5zPcdz +OAj84VwO4p1cGAguc5vvH3+0b62NpUlbNCECAwEAAaOCAZ8wggGbMA4GA1UdDwEB +/wQEAwIBBjBRBgNVHSAESjBIMEYGBFUdIAAwPjA8BggrBgEFBQcCARYwaHR0cDov +L2dyaWQtZnIucG5jbi5lZHVjYXRpb24uZ291di5mci9wYy1ncmlkLWZyMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5ncmlk +LWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvYWMtZ3JpZC1mci5jcmwwgZYGCCsG +AQUFBwEBBIGJMIGGMEQGCCsGAQUFBzAChjhodHRwOi8vY2VyLmdyaWQtZnIucG5j +bi5lZHVjYXRpb24uZ291di5mci9hYy1ncmlkLWZyLmNlcjA+BggrBgEFBQcwAYYy +aHR0cDovL29jc3AuZ3JpZC1mci5wbmNuLmVkdWNhdGlvbi5nb3V2LmZyL2dyaWQt +ZnIwHQYDVR0OBBYEFN49xvEGIjeZn88iCJUA5wHioLwQMB8GA1UdIwQYMBaAFKoM +1rz52WU9cIpRMCCPTP7NYLnjMA0GCSqGSIb3DQEBCwUAA4IBgQBxa53DK6bHVXcv +5Uo+QIgpi43ybbXlSY/7a2fFiMZLRiJ/gpm9qicZUAfNbXIG8eY7i6SCIIFa/on4 +0CnZjPeFy7Hi4HZwFpT4Mdu6G5yAV94k70sWqi5Vfdcv0PO37GI0QyxqtzTCB07n +JhhE/uyYuwLryXXOUq/r4z2O1N4OZyeALiA/ojO0oQxzuULoveFyasd05tmmPD+r +TEePaoly889oH61GbOvYx7syO2AoViVGa2kZX5qUqfVhiYa3vd1uhU8UGqs8iHWW +f8BaCawV7GpJ8yx4+rlLHT5nzLcrg8+c8tGHuoFLgPdS3WuJXNrQjtwfd95u/Rx0 +mQUm5QDZgIdYSJmYYt6fVyqxRrszSOcS/6qsVeethyqP0ni5jsQjxiWz1jb2cfiT +Er1nrK8Z3F4wm+pLovR5em7ck1BayNUmcXonsfHcUZVb/skfLxxVu7znPI8epMz+ +5EgHvw2trURiay3DlgXy6uj5tp/PbG6V+UtgH5Iso9WzByLXcuk= +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/80df9b28.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/80df9b28.signing_policy new file mode 100644 index 00000000..a0d33932 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/80df9b28.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR-Personnels.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/O=GRID-FR/*"' diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.crl_url b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.crl_url new file mode 100644 index 00000000..4341e725 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.crl_url @@ -0,0 +1 @@ +http://crl.grid-fr.pncn.education.gouv.fr/ac-grid-fr-personnels.crl diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.info b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.info new file mode 100644 index 00000000..8cc715de --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.info @@ -0,0 +1,11 @@ +# +# @(#)$Id: AC-GRID-FR-Personnels.info,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +alias = AC-GRID-FR-Personnels +url = http://grid-fr.renater.fr/ +email = grid-fr@renater.fr +ca_url = http://cer.grid-fr.pncn.education.gouv.fr/ac-grid-fr-personnels.cer +crl_url = http://crl.grid-fr.pncn.education.gouv.fr/ac-grid-fr-personnels.crl +status = accredited:classic +version = 1.90 +sha1fp.0 = CA:F3:29:BD:77:67:9E:06:05:DB:1D:41:DF:7A:77:76:F1:78:2A:A9 +subjectdn = "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.pem b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.pem new file mode 100644 index 00000000..3bae8f59 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCBCqgAwIBAgISESEbWlKSHT/Bwe1tXK8w0TWHMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBQMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMR4wHAYDVQQDDBVBQyBHUklELUZSIFBlcnNvbm5lbHMwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDWvrNF8vQ5jpSvmXPzEhBp958C43rp +DMTcQWWd0A78t1aKizc+gNAso2KQivjt1Yu/KiMSjpi85LEOKOB3OESUY6c+slfV +L5psH5bwif6zu5guiLFtd/XmRGC4wFHh1Zo8NTply0NlzaN9/bY+BQnlstexbiGe +Mm3W7AfzNmmszykgIegoOmAlk1P2Snxbk5kCO/uQlezQzNLUFB5OYE/DL4gOpONE +Xa470fCCToSUrJ2HlteU0il/8tSgBws2xENUzA/r/ZmwG6IeVHYxukK4SzOn8fFU +sLoNE0srlDz8Xgdr9XZyEFdQXJ4IsWGgGLyKsnN/jwPsZ7qkhvaDbKdml7i1S5F9 +PZf1hSgwRgx2C4NP4JZacWiG+UNTk1XM0ZiIUTjhMN+isqOHiUKRBXyg9gLw01RP +mOrA8xjzt2VjkobSdgA/9R7p+sdYTWCMsgAaPd2P5ZO1XrvRCkfUk5jKSw5zPcdz +OAj84VwO4p1cGAguc5vvH3+0b62NpUlbNCECAwEAAaOCAZ8wggGbMA4GA1UdDwEB +/wQEAwIBBjBRBgNVHSAESjBIMEYGBFUdIAAwPjA8BggrBgEFBQcCARYwaHR0cDov +L2dyaWQtZnIucG5jbi5lZHVjYXRpb24uZ291di5mci9wYy1ncmlkLWZyMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5ncmlk +LWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvYWMtZ3JpZC1mci5jcmwwgZYGCCsG +AQUFBwEBBIGJMIGGMEQGCCsGAQUFBzAChjhodHRwOi8vY2VyLmdyaWQtZnIucG5j +bi5lZHVjYXRpb24uZ291di5mci9hYy1ncmlkLWZyLmNlcjA+BggrBgEFBQcwAYYy +aHR0cDovL29jc3AuZ3JpZC1mci5wbmNuLmVkdWNhdGlvbi5nb3V2LmZyL2dyaWQt +ZnIwHQYDVR0OBBYEFN49xvEGIjeZn88iCJUA5wHioLwQMB8GA1UdIwQYMBaAFKoM +1rz52WU9cIpRMCCPTP7NYLnjMA0GCSqGSIb3DQEBCwUAA4IBgQBxa53DK6bHVXcv +5Uo+QIgpi43ybbXlSY/7a2fFiMZLRiJ/gpm9qicZUAfNbXIG8eY7i6SCIIFa/on4 +0CnZjPeFy7Hi4HZwFpT4Mdu6G5yAV94k70sWqi5Vfdcv0PO37GI0QyxqtzTCB07n +JhhE/uyYuwLryXXOUq/r4z2O1N4OZyeALiA/ojO0oQxzuULoveFyasd05tmmPD+r +TEePaoly889oH61GbOvYx7syO2AoViVGa2kZX5qUqfVhiYa3vd1uhU8UGqs8iHWW +f8BaCawV7GpJ8yx4+rlLHT5nzLcrg8+c8tGHuoFLgPdS3WuJXNrQjtwfd95u/Rx0 +mQUm5QDZgIdYSJmYYt6fVyqxRrszSOcS/6qsVeethyqP0ni5jsQjxiWz1jb2cfiT +Er1nrK8Z3F4wm+pLovR5em7ck1BayNUmcXonsfHcUZVb/skfLxxVu7znPI8epMz+ +5EgHvw2trURiay3DlgXy6uj5tp/PbG6V+UtgH5Iso9WzByLXcuk= +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.signing_policy new file mode 100644 index 00000000..a0d33932 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR-Personnels.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR-Personnels.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/O=GRID-FR/*"' diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.crl_url b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.crl_url new file mode 100644 index 00000000..d83742aa --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.crl_url @@ -0,0 +1 @@ +http://crl.grid-fr.pncn.education.gouv.fr/ac-grid-fr.crl diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.info b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.info new file mode 100644 index 00000000..27f78ad2 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.info @@ -0,0 +1,11 @@ +# +# @(#)$Id: AC-GRID-FR.info,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +alias = AC-GRID-FR +url = http://grid-fr.renater.fr/ +email = grid-fr@renater.fr +ca_url = http://cer.grid-fr.pncn.education.gouv.fr/ac-grid-fr.cer +crl_url = http://crl.grid-fr.pncn.education.gouv.fr/ac-grid-fr.crl +status = accredited:classic +version = 1.90 +sha1fp.0 = 38:9D:99:0D:6A:6E:6C:68:AC:B5:9F:F6:03:5D:38:1C:A7:40:29:60 +subjectdn = "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.namespaces b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.namespaces new file mode 100644 index 00000000..7f3211f7 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.namespaces @@ -0,0 +1,28 @@ +############################################################################## +#NAMESPACES-VERSION: 1.0 +# +# @(#)AC-GRID-FR.signing_policy.namespaces +# CA alias : AC-GRID-FR +# subord_of: +# subjectDN: /C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR +# hash : AC-GRID-FR.signing_policy +# (generated automatically from AC-GRID-FR.signing_policy) +# +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" \ + PERMIT Subject "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" \ + PERMIT Subject "/O=GRID-FR/.*" + +TO Issuer "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services" \ + PERMIT Subject "/O=GRID-FR/.*" + diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.pem b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.pem new file mode 100644 index 00000000..87639813 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzjCCAzagAwIBAgISESHcZGpjVbhv3LcwHBxmFWKhMA0GCSqGSIb3DQEBCwUA +MEUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQKDAZNRU5FU1IxEDAOBgNVBAsMB0dSSUQt +RlIxEzARBgNVBAMMCkFDIEdSSUQtRlIwHhcNMTYwOTMwMDgwMDAwWhcNNDAwOTMw +MDgwMDAwWjBFMQswCQYDVQQGEwJGUjEPMA0GA1UECgwGTUVORVNSMRAwDgYDVQQL +DAdHUklELUZSMRMwEQYDVQQDDApBQyBHUklELUZSMIIBojANBgkqhkiG9w0BAQEF +AAOCAY8AMIIBigKCAYEAywcrhCkF87S7e/Sfc0S+QGS4ED9EuYvoQj8KiWlyz9UF +nccNtjaxnlJbaGU6myNreeEEbt+QdydQ/vkPQd2gEhoxirz6VDJgRg2i56Zw/JL9 +FVcmDgKG6t7Ap9/NB3MobXWPd7yQu7SIfnd3BnLW87tOdILpiODZNOWeh6Qg1Fgn +aFHRjVPN6ugU1qbW44sPDv0yFhNRfnsDomVOewRg46fxv8tah+lIYsVulGYVhmkI +AgNs9YMTclukxPL5YOFgeY+3A+G/1NwKmteFqBIQRcaF1UbHrSsn6H5cIdsEJ1NT +IBPYuDGD/SkH5dFpOeyZ+RLxCaoI4W+dVyYhVealdrtmI2XQL7lLWLTHJzZqRBcA +gc60J2bjZl3HwxFE/QKW5f67zLkupFPO61OWeAl+pwIIE4Xo6z0ubNrLg5MqiO7G +7YOPocSlkBMIv+OzhrzMxsZpjSaLm32/nGyj0T+XQwUN4gK87VkHa0lz+qU6TTG0 +bggGOK72rcXdGZWlzGfzAgMBAAGjgbcwgbQwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wUQYDVR0gBEowSDBGBgRVHSAAMD4wPAYIKwYBBQUHAgEWMGh0 +dHA6Ly9ncmlkLWZyLnBuY24uZWR1Y2F0aW9uLmdvdXYuZnIvcGMtZ3JpZC1mcjAd +BgNVHQ4EFgQUqgzWvPnZZT1wilEwII9M/s1gueMwHwYDVR0jBBgwFoAUqgzWvPnZ +ZT1wilEwII9M/s1gueMwDQYJKoZIhvcNAQELBQADggGBAIGprfsrGbphQnPMyshh +SOB+Q/hLV3vSyT52kSuifHMHkoLA61cJT/Lrp5Vb2yKi7SWzbWrCD4dNsbTAt838 +7WZUVeSkvvqJmDeMI/Jj4LVMVSnLsxFHwrphw1KiEen2kZL8BmbTRW1x3UnuF7Dx +Evr/Um7O+gZFg0SHCVCeCpYYROLZOFre98lvvYRn2vixKPSXxDkfaeW4B91SD3is +qMW8ATtq3Wp5ZOGRlMzCEEt2OmLnSYldkjb/I1Noi3A9Uzwuxxm9vDfG291uI6ks +wMpYrwVXjoUZWZ1FSf766SBtAzLPYjcpmJwRvTIxNyMWedZCMbkKhRL9z1ZhEMbR +chLvh3mnrDdFbUoCCQ4ZqmcgYIgw3+JzIf3vRszPpJirJ0ZoZKrBs4QRDdlFZtON +kBA7U1h+lAzYSExpZPoF8m7meKtL9oanlJ66XLGv0yg6N7oL1mvPkR/QiLSrOeRI ++yS8kr+zh4fpr9gRJUQkxA+xGSiGUk9DZwK0TA/3WICj7w== +-----END CERTIFICATE----- diff --git a/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.signing_policy b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.signing_policy new file mode 100644 index 00000000..1ae6cbd1 --- /dev/null +++ b/voms-admin-server/src/test/resources/trust-anchors/AC-GRID-FR.signing_policy @@ -0,0 +1,5 @@ +# @(#)$Id: AC-GRID-FR.signing_policy,v 1.1 2018/03/06 07:56:31 pmacvsdg Exp $ +# Root +access_id_CA X509 '/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR' +pos_rights globus CA:sign +cond_subjects globus '"/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Robots" "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Services"' From de8f5ec9382652e63913df18f4819d6ad0118e4b Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 8 May 2018 18:45:12 +0200 Subject: [PATCH 17/63] Fix namespace resolution logic VOMS Admin failed in resolving a namespace policy for a CA when such policy was defined not at the leaf CA level but at an higher level in the trust-anchors chain. This commit fixes that problem. Issue: https://issues.infn.it/jira/browse/VOMS-835 --- .../util/validation/x509/CanlDNValidator.java | 105 ++++++++++++------ .../view/actions/audit/ExportCSVAction.java | 25 ----- .../java/validation/DnValidationTest.java | 19 +++- 3 files changed, 87 insertions(+), 62 deletions(-) delete mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/ExportCSVAction.java diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java index 2f1e0bc5..4fd838db 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java @@ -1,23 +1,25 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. */ package org.glite.security.voms.admin.util.validation.x509; +import static java.util.Objects.isNull; + import java.io.IOException; +import java.security.cert.TrustAnchor; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Timer; import java.util.concurrent.TimeUnit; @@ -28,6 +30,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.Lists; + import eu.emi.security.authn.x509.NamespaceCheckingMode; import eu.emi.security.authn.x509.StoreUpdateListener; import eu.emi.security.authn.x509.helpers.ObserversHandler; @@ -39,31 +43,63 @@ public class CanlDNValidator implements DnValidator, StoreUpdateListener { - public static final Logger LOG = LoggerFactory - .getLogger(CanlDNValidator.class); + public static final Logger LOG = LoggerFactory.getLogger(CanlDNValidator.class); final OpensslTrustAnchorStore trustAnchorStore; final Timer trustStoreTimer = new Timer("CanlDNValidator timer", true); final NamespaceCheckingMode nsMode = NamespaceCheckingMode.EUGRIDPMA_AND_GLOBUS_REQUIRE; public CanlDNValidator(String trustAnchorsDir, boolean openssl1Mode) { - trustAnchorStore = new OpensslTrustAnchorStoreImpl(trustAnchorsDir, - trustStoreTimer, TimeUnit.HOURS.toMillis(4), nsMode.globusEnabled(), - nsMode.euGridPmaEnabled(), - new ObserversHandler(Collections.singletonList(this)), openssl1Mode); + trustAnchorStore = new OpensslTrustAnchorStoreImpl(trustAnchorsDir, trustStoreTimer, + TimeUnit.HOURS.toMillis(4), nsMode.globusEnabled(), nsMode.euGridPmaEnabled(), + new ObserversHandler(Collections.singletonList(this)), openssl1Mode); + } + + X500Principal resolveParentPrincipal(X500Principal principal) { + for (TrustAnchor anchor : trustAnchorStore.getTrustAnchors()) { + if (anchor.getTrustedCert().getSubjectX500Principal().equals(principal)) { + X500Principal parentCaPrincipal = anchor.getTrustedCert().getIssuerX500Principal(); + if (parentCaPrincipal.equals(principal)) { + return null; + } else { + return parentCaPrincipal; + } + } + } + return null; + } + + X500Principal[] resolveX500PrincipalChain(X500Principal principal) { + List caSubjects = Lists.newArrayList(); + caSubjects.add(principal); + X500Principal p = principal; + + while (true) { + X500Principal parentPrincipal = resolveParentPrincipal(p); + if (isNull(parentPrincipal)) { + break; + } + caSubjects.add(parentPrincipal); + p = parentPrincipal; + } + + return caSubjects.toArray(new X500Principal[caSubjects.size()]); + } + + List resolveNamespacePolicies(X500Principal principal) { + X500Principal[] chainOfPrincipals = resolveX500PrincipalChain(principal); + return trustAnchorStore.getPmaNsStore().getPolicies(chainOfPrincipals, 0); } @SuppressWarnings("deprecation") @Override - public DnValidationResult validate(String issuerSubject, - String certificateSubject) { + public DnValidationResult validate(String issuerSubject, String certificateSubject) { Validate.notNull(issuerSubject, "issuerSubject must be non-null"); Validate.notNull(certificateSubject, "certificateSubject must be non-null"); String issuerSubjectRfc = OpensslNameUtils.opensslToRfc2253(issuerSubject); - String certificateSubjectRfc = OpensslNameUtils - .opensslToRfc2253(certificateSubject); + String certificateSubjectRfc = OpensslNameUtils.opensslToRfc2253(certificateSubject); LOG.debug("issuer rfc2253 string: {}", issuerSubjectRfc); LOG.debug("subject rfc2253 string: {}", certificateSubjectRfc); @@ -76,44 +112,41 @@ public DnValidationResult validate(String issuerSubject, subjectPrincipal = X500NameUtils.getX500Principal(certificateSubjectRfc); } catch (IOException e) { - LOG.error("Error converting subject to X500Principal: {}", e.getMessage(), - e); + LOG.error("Error converting subject to X500Principal: {}", e.getMessage(), e); throw new DnValidationError(e.getMessage(), e); } - List policies = trustAnchorStore.getPmaNsStore() - .getPolicies(new X500Principal[] { subjectPrincipal, issuerPrincipal }, - 1); + List policies = resolveNamespacePolicies(issuerPrincipal); - DnValidationResult.Builder resultBuilder = DnValidationResult.build() - .dn(subjectPrincipal) - .ca(issuerPrincipal); + DnValidationResult.Builder resultBuilder = + DnValidationResult.build().dn(subjectPrincipal).ca(issuerPrincipal); if (policies == null || policies.isEmpty()) { resultBuilder.error(ValidationError.NAMESPACE_NOT_FOUND); return resultBuilder.build(); } + DnValidationResult result = null; + for (NamespacePolicy p : policies) { if (p.isSubjectMatching(subjectPrincipal)) { LOG.debug("Found matching policy {} for subject {}. Permit: {}", - new Object[] { p.getIdentification(), subjectPrincipal, - new Boolean(p.isPermit()) }); - - return resultBuilder.policy(p) - .build(); + new Object[] {p.getIdentification(), subjectPrincipal, new Boolean(p.isPermit())}); + result = resultBuilder.policy(p).build(); } } + if (!Objects.isNull(result)) { + return result; + } + LOG.debug("No policy found for subject {}", subjectPrincipal); - return resultBuilder.error(ValidationError.NO_MATCHING_POLICY) - .build(); + return resultBuilder.error(ValidationError.NO_MATCHING_POLICY).build(); } @Override - public void loadingNotification(String location, String type, Severity level, - Exception cause) { + public void loadingNotification(String location, String type, Severity level, Exception cause) { } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/ExportCSVAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/ExportCSVAction.java deleted file mode 100644 index 958ef89f..00000000 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/audit/ExportCSVAction.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.glite.security.voms.admin.view.actions.audit; - -import org.glite.security.voms.admin.view.actions.BaseAction; - - -public class ExportCSVAction extends BaseAction { - - - -} diff --git a/voms-admin-server/src/test/java/validation/DnValidationTest.java b/voms-admin-server/src/test/java/validation/DnValidationTest.java index 3567b4cd..e0d3a7ad 100644 --- a/voms-admin-server/src/test/java/validation/DnValidationTest.java +++ b/voms-admin-server/src/test/java/validation/DnValidationTest.java @@ -15,6 +15,11 @@ */ package validation; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + import org.glite.security.voms.admin.util.validation.x509.CanlDNValidator; import org.glite.security.voms.admin.util.validation.x509.DnValidationResult; import org.glite.security.voms.admin.util.validation.x509.DnValidationResult.ValidationError; @@ -68,8 +73,20 @@ public void testUnkownCaValidationError() { DnValidationResult result = validator.validate(UNKNOWN_CA_SUBJECT, "/CN=Ciccio"); - Assert.assertEquals(ValidationError.NAMESPACE_NOT_FOUND, result.getError()); + assertEquals(ValidationError.NAMESPACE_NOT_FOUND, result.getError()); } + + @Test + public void testFrenchCaValidationError() { + + DnValidationResult result = + validator.validate( + "/C=FR/O=MENESR/OU=GRID-FR/CN=AC GRID-FR Personnels", + "/O=GRID-FR/C=FR/O=CNRS/OU=LLR/CN=Whatever"); + + assertThat(result.getError(), nullValue()); + assertThat(result.isValid(), is(true)); + } } From 98159aa50998b634e047b6f30b9c8f6f5e47330b Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 9 May 2018 11:07:07 +0200 Subject: [PATCH 18/63] Jenkinsfile: fix syntax --- Jenkinsfile | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e476d3fd..7df2e828 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,8 +13,10 @@ pipeline { stage('build') { steps { - git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) - sh 'mvn -B -U -P prod,EMI clean package' + container('maven-runner') { + git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) + sh 'mvn -B -U -P prod,EMI clean package' + } } } @@ -24,13 +26,15 @@ pipeline { expression { return params.BUILD_DOCKER_IMAGES } } steps { - sh ''' - pushd docker/voms-admin-server - sh build-image.sh && sh push-image.sh - popd - push docker/voms/centos6 - sh build-image.sh && sh push-image.sh - popd''' + container('docker-runner') { + sh ''' + pushd docker/voms-admin-server + sh build-image.sh && sh push-image.sh + popd + push docker/voms/centos6 + sh build-image.sh && sh push-image.sh + popd''' + } } } } From c71728dc224bff7ea1b1ec49d47448f7f7bf7c98 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 10 May 2018 12:31:53 +0200 Subject: [PATCH 19/63] Avoid duplicate entries in warning message The Criteria query used to resolve members about to expire didn't properly select distinct users. This commit provides a fix to that problem (moving the query to HQL) and other small fixes in the email templates. Issue: https://issues.infn.it/jira/browse/VOMS-832 --- .../admin/persistence/dao/VOMSUserDAO.java | 568 +++++++----------- .../templates/ExpiredMembersWarning.vm | 8 +- .../templates/MembershipExpirationWarning.vm | 4 +- .../src/main/webapp/style/badge.css | 3 +- 4 files changed, 241 insertions(+), 342 deletions(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index eaf1c6e7..e125dc42 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -1,17 +1,15 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. */ package org.glite.security.voms.admin.persistence.dao; @@ -63,14 +61,10 @@ import org.glite.security.voms.admin.persistence.model.task.SignAUPTask; import org.glite.security.voms.admin.util.DNUtil; import org.hibernate.CacheMode; -import org.hibernate.Criteria; import org.hibernate.ObjectNotFoundException; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; -import org.hibernate.criterion.Order; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -99,11 +93,9 @@ public void requestAUPReacceptance(VOMSUser user, AUP aup) { AUPVersion aupVersion = aup.getActiveVersion(); if (aupVersion == null) - throw new NotFoundException( - "No registered version found for AUP '" + aup.getName() + "'."); + throw new NotFoundException("No registered version found for AUP '" + aup.getName() + "'."); - log.debug("User '" + user + "' is request to reaccept aup version '" - + aupVersion + "'"); + log.debug("User '" + user + "' is request to reaccept aup version '" + aupVersion + "'"); AUPAcceptanceRecord r = user.getAUPAccceptanceRecord(aupVersion); @@ -119,9 +111,7 @@ public void requestAUPReacceptance(VOMSUser user, AUP aup) { public void signAUP(VOMSUser user) { - signAUP(user, DAOFactory.instance() - .getAUPDAO() - .getVOAUP()); + signAUP(user, DAOFactory.instance().getAUPDAO().getVOAUP()); } public void signAUP(VOMSUser user, AUP aup) { @@ -135,8 +125,7 @@ public void signAUP(VOMSUser user, AUP aup) { AUPVersion aupVersion = aup.getActiveVersion(); if (aupVersion == null) - throw new NotFoundException( - "No registered version found for AUP '" + aup.getName() + "'."); + throw new NotFoundException("No registered version found for AUP '" + aup.getName() + "'."); log.debug("User '" + user + "' signing aup version '" + aupVersion + "'"); @@ -148,8 +137,7 @@ public void signAUP(VOMSUser user, AUP aup) { AUPAcceptanceRecord aupRecord = new AUPAcceptanceRecord(user, aupVersion); aupRecord.setLastAcceptanceDate(new Date()); - user.getAupAcceptanceRecords() - .add(aupRecord); + user.getAupAcceptanceRecords().add(aupRecord); } else { @@ -174,25 +162,24 @@ public void signAUP(VOMSUser user, AUP aup) { } while (pendingTask != null); - if (user.isSuspended() && user.getSuspensionReasonCode() - .equals(SuspensionReason.FAILED_TO_SIGN_AUP)) { + if (user.isSuspended() + && user.getSuspensionReasonCode().equals(SuspensionReason.FAILED_TO_SIGN_AUP)) { log.debug("Restoring user '" + user + "'"); user.restore(SuspensionReason.FAILED_TO_SIGN_AUP); } - HibernateFactory.getSession() - .saveOrUpdate(user); + HibernateFactory.getSession().saveOrUpdate(user); } @SuppressWarnings("unchecked") public List findUsersWithPendingSignAUPTask(AUP aup) { - String queryString = "from VOMSUser u join u.tasks t where t.class = SignAUPTask and t.status != 'COMPLETED' and t.aup = :aup"; + String queryString = + "from VOMSUser u join u.tasks t where t.class = SignAUPTask and t.status != 'COMPLETED' and t.aup = :aup"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); q.setEntity("aup", aup); return q.list(); @@ -205,8 +192,7 @@ public Long countExpiredUsers() { String queryString = "select count(*) from VOMSUser u where u.endTime < :now"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); q.setDate("now", now); @@ -220,8 +206,7 @@ public List findExpiredUsers() { Date now = new Date(); String queryString = "from VOMSUser u where u.endTime is not null and u.endTime < :now"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); q.setDate("now", now); @@ -237,24 +222,23 @@ public List findAUPFailingUsers(AUP aup) { // Get users First that do not have any acceptance records for the // active aupVersion - String noAcceptanceRecordForActiveAUPVersionQuery = "select u from VOMSUser u where u not in (select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true)"; + String noAcceptanceRecordForActiveAUPVersionQuery = + "select u from VOMSUser u where u not in (select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true)"; - Query q = HibernateFactory.getSession() - .createQuery(noAcceptanceRecordForActiveAUPVersionQuery); + Query q = HibernateFactory.getSession().createQuery(noAcceptanceRecordForActiveAUPVersionQuery); List noRecordUsers = q.list(); result.addAll(noRecordUsers); - log.debug("Users without acceptance records for currently active aup: {}", - result); + log.debug("Users without acceptance records for currently active aup: {}", result); // Add users that have an expired aup acceptance record due to aup // update or acceptance retriggering. - String qString = "select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true and r.lastAcceptanceDate < :lastUpdateTime"; + String qString = + "select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true and r.lastAcceptanceDate < :lastUpdateTime"; - Query q2 = HibernateFactory.getSession() - .createQuery(qString); + Query q2 = HibernateFactory.getSession().createQuery(qString); Date aupLastUpdateTime = activeVersion.getLastUpdateTime(); @@ -264,25 +248,21 @@ public List findAUPFailingUsers(AUP aup) { List expiredDueToAUPUpdateUsers = q2.list(); result.addAll(expiredDueToAUPUpdateUsers); - log.debug("Users that signed the AUP before it was last updated:" - + expiredDueToAUPUpdateUsers); + log.debug("Users that signed the AUP before it was last updated:" + expiredDueToAUPUpdateUsers); // Add users that have a valid aup acceptance record that needs to be // checked against // the reacceptance period - Query q3 = HibernateFactory.getSession() - .createQuery( + Query q3 = HibernateFactory.getSession().createQuery( "select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true" - + " and r.lastAcceptanceDate > :lastUpdateTime "); + + " and r.lastAcceptanceDate > :lastUpdateTime "); q3.setTimestamp("lastUpdateTime", aupLastUpdateTime); List potentiallyExpiredUsers = q3.list(); - HibernateFactory.getSession() - .flush(); + HibernateFactory.getSession().flush(); - log.debug( - "Users that needs checking since their aup acceptance record could be expired:" + log.debug("Users that needs checking since their aup acceptance record could be expired:" + potentiallyExpiredUsers); for (VOMSUser u : potentiallyExpiredUsers) { @@ -290,8 +270,9 @@ public List findAUPFailingUsers(AUP aup) { AUPAcceptanceRecord r = u.getAUPAccceptanceRecord(aup.getActiveVersion()); if (r.hasExpired()) { - log.debug("Adding user{} to results due to expired aup acceptance report (aup validity expiration)", - u); + log.debug( + "Adding user{} to results due to expired aup acceptance report (aup validity expiration)", + u); result.add(u); } @@ -300,15 +281,14 @@ public List findAUPFailingUsers(AUP aup) { // Filter out expired users ListIterator iter = result.listIterator(); - while (iter.hasNext()){ + while (iter.hasNext()) { VOMSUser u = iter.next(); - if (u.hasExpired() && u.isSuspended()){ - log.debug("Removing supended user {} from results since " - + "membership expired", u); + if (u.hasExpired() && u.isSuspended()) { + log.debug("Removing supended user {} from results since " + "membership expired", u); iter.remove(); } } - + return result; } @@ -319,13 +299,11 @@ public Certificate addCertificate(VOMSUser u, String dn, String caDn) { Validate.notEmpty(dn, "DN must be non-null & not empty!"); Validate.notEmpty(caDn, "CA must be non-null & not empty!"); - VOMSCA ca = VOMSCADAO.instance() - .getByName(caDn); + VOMSCA ca = VOMSCADAO.instance().getByName(caDn); if (ca == null) throw new NoSuchCAException("CA '" + caDn + "' not found in database."); - Certificate cert = CertificateDAO.instance() - .lookup(dn, caDn); + Certificate cert = CertificateDAO.instance().lookup(dn, caDn); if (cert != null) throw new AlreadyExistsException("Certificate already bound!"); @@ -344,10 +322,8 @@ public Certificate addCertificate(VOMSUser u, String dn, String caDn) { cert.setSuspensionReason(u.getSuspensionReason()); } - HibernateFactory.getSession() - .saveOrUpdate(cert); - HibernateFactory.getSession() - .saveOrUpdate(u); + HibernateFactory.getSession().saveOrUpdate(cert); + HibernateFactory.getSession().saveOrUpdate(u); return cert; @@ -362,22 +338,19 @@ public Certificate addCertificate(VOMSUser u, X509Certificate x509Cert) { // at this stage. String caDN = DNUtil.getOpenSSLSubject(x509Cert.getIssuerX500Principal()); - VOMSCA ca = VOMSCADAO.instance() - .getByName(caDN); + VOMSCA ca = VOMSCADAO.instance().getByName(caDN); if (ca == null) throw new NoSuchCAException("CA '" + caDN + "' not recognized!"); - Certificate cert = CertificateDAO.instance() - .find(x509Cert); + Certificate cert = CertificateDAO.instance().find(x509Cert); if (cert != null) throw new AlreadyExistsException("Certificate already bound!"); cert = new Certificate(); - String subjectString = DNUtil - .getOpenSSLSubject(x509Cert.getSubjectX500Principal()); + String subjectString = DNUtil.getOpenSSLSubject(x509Cert.getSubjectX500Principal()); cert.setSubjectString(subjectString); cert.setCreationTime(new Date()); cert.setSuspended(false); @@ -392,10 +365,8 @@ public Certificate addCertificate(VOMSUser u, X509Certificate x509Cert) { u.addCertificate(cert); - HibernateFactory.getSession() - .saveOrUpdate(cert); - HibernateFactory.getSession() - .saveOrUpdate(u); + HibernateFactory.getSession().saveOrUpdate(cert); + HibernateFactory.getSession().saveOrUpdate(u); return cert; @@ -405,72 +376,58 @@ public void addToGroup(VOMSUser u, VOMSGroup g) { log.debug("Adding user \"" + u + "\" to group \"" + g + "\"."); - if (!HibernateFactory.getSession() - .contains(u)) { + if (!HibernateFactory.getSession().contains(u)) { VOMSUser checkUser = findById(u.getId()); if (checkUser == null) - throw new NoSuchUserException( - "User \"" + u + "\" not found in database."); + throw new NoSuchUserException("User \"" + u + "\" not found in database."); } // Check that the group exists - if (VOMSGroupDAO.instance() - .findByName(g.getName()) == null) - throw new NoSuchGroupException( - "Group \"" + g + "\" is not defined in database."); + if (VOMSGroupDAO.instance().findByName(g.getName()) == null) + throw new NoSuchGroupException("Group \"" + g + "\" is not defined in database."); VOMSMapping m = new VOMSMapping(u, g, null); - if (u.getMappings() - .contains(m)) + if (u.getMappings().contains(m)) throw new AlreadyMemberException( - "User \"" + u + "\" is already a member of group \"" + g + "\"."); + "User \"" + u + "\" is already a member of group \"" + g + "\"."); - u.getMappings() - .add(m); + u.getMappings().add(m); - HibernateFactory.getSession() - .save(u); + HibernateFactory.getSession().save(u); } public void assignRole(VOMSUser u, VOMSGroup g, VOMSRole r) { u.assignRole(g, r); - HibernateFactory.getSession() - .update(u); + HibernateFactory.getSession().update(u); } @SuppressWarnings("deprecation") private void checkNullFields(VOMSUser usr) { - if (!VOMSConfiguration.instance() - .getBoolean("voms.admin.compatibility-mode", true)) { + if (!VOMSConfiguration.instance().getBoolean("voms.admin.compatibility-mode", true)) { if (usr.getName() == null) throw new NullArgumentException("Please specify a name for the user!"); if (usr.getSurname() == null) - throw new NullArgumentException( - "Please specify a surname for the user!"); + throw new NullArgumentException("Please specify a surname for the user!"); if (usr.getInstitution() == null) - throw new NullArgumentException( - "Please specify an instituion for the user!"); + throw new NullArgumentException("Please specify an instituion for the user!"); if (usr.getAddress() == null) - throw new NullArgumentException( - "Please specify an address for the user!"); + throw new NullArgumentException("Please specify an address for the user!"); if (usr.getPhoneNumber() == null) - throw new NullArgumentException( - "Please specify a phone number for the user!"); + throw new NullArgumentException("Please specify a phone number for the user!"); if (usr.getEmailAddress() == null) - throw new NullArgumentException( - "Please specify an email address for the user!"); + throw new NullArgumentException("Please specify an email address for the user!"); } else { @@ -478,8 +435,7 @@ private void checkNullFields(VOMSUser usr) { throw new NullArgumentException("Please specify a dn for the user!"); if (usr.getEmailAddress() == null) - throw new NullArgumentException( - "Please specify an email address for the user!"); + throw new NullArgumentException("Please specify an email address for the user!"); } } @@ -488,14 +444,14 @@ public int countMatches(String searchString) { String sString = "%" + searchString + "%"; - String countString = "select count(distinct u) from VOMSUser u join u.certificates as cert where lower(u.surname) like lower(:searchString) " - + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " - + " or lower(u.institution) like lower(:searchString) " - + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString) " - + " order by u.surname asc"; + String countString = + "select count(distinct u) from VOMSUser u join u.certificates as cert where lower(u.surname) like lower(:searchString) " + + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " + + " or lower(u.institution) like lower(:searchString) " + + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString) " + + " order by u.surname asc"; - Query q = HibernateFactory.getSession() - .createQuery(countString); + Query q = HibernateFactory.getSession().createQuery(countString); q.setString("searchString", sString); Long count = (Long) q.uniqueResult(); @@ -506,16 +462,14 @@ public int countMatches(String searchString) { public Long countUsers() { - Query q = HibernateFactory.getSession() - .createQuery("select count(*) from VOMSUser"); + Query q = HibernateFactory.getSession().createQuery("select count(*) from VOMSUser"); Long count = (Long) q.uniqueResult(); return count; } - public VOMSUser create(String dn, String caDN, String cn, String certURI, - String emailAddress) { + public VOMSUser create(String dn, String caDN, String cn, String certURI, String emailAddress) { if (dn == null) throw new NullArgumentException("dn must be non-null!"); @@ -535,12 +489,10 @@ public VOMSUser create(String dn, String caDN, String cn, String certURI, throw new UserAlreadyExistsException("User " + u + " already exists!"); } - VOMSCA ca = VOMSCADAO.instance() - .getByName(caDN); + VOMSCA ca = VOMSCADAO.instance().getByName(caDN); if (ca == null) { - throw new NoSuchCAException( - "Unknown ca " + caDN + ". Will not create user " + dn); + throw new NoSuchCAException("Unknown ca " + caDN + ". Will not create user " + dn); } u = new VOMSUser(); @@ -550,18 +502,15 @@ public VOMSUser create(String dn, String caDN, String cn, String certURI, // Add user to default VO group - VOMSGroup voGroup = VOMSGroupDAO.instance() - .getVOGroup(); - HibernateFactory.getSession() - .save(u); + VOMSGroup voGroup = VOMSGroupDAO.instance().getVOGroup(); + HibernateFactory.getSession().save(u); addToGroup(u, voGroup); return u; } - public VOMSUser create(VOMSUserJSON usr, String certificateSubject, - String caSubject) { + public VOMSUser create(VOMSUserJSON usr, String certificateSubject, String caSubject) { VOMSUser u = VOMSUser.fromVOMSUserJSON(usr); @@ -570,8 +519,7 @@ public VOMSUser create(VOMSUserJSON usr, String certificateSubject, } - protected Certificate createCertificate(String certificateSubject, - String caSubject) { + protected Certificate createCertificate(String certificateSubject, String caSubject) { CertificateDAO certDAO = CertificateDAO.instance(); @@ -579,8 +527,7 @@ protected Certificate createCertificate(String certificateSubject, } - protected Certificate lookupCertificate(String certificateSubject, - String certificateIssuer) { + protected Certificate lookupCertificate(String certificateSubject, String certificateIssuer) { CertificateDAO certDAO = CertificateDAO.instance(); Certificate cert = certDAO.lookup(certificateSubject, certificateIssuer); @@ -588,15 +535,14 @@ protected Certificate lookupCertificate(String certificateSubject, return cert; } - protected Certificate assertCertificateIsNotBound(String certificateSubject, - String caSubject) { + protected Certificate assertCertificateIsNotBound(String certificateSubject, String caSubject) { Certificate cert = lookupCertificate(certificateSubject, caSubject); if (cert != null) throw new UserAlreadyExistsException( - "A user holding a certificate with the following subject '" - + certificateSubject + "' already exists in this VO."); + "A user holding a certificate with the following subject '" + certificateSubject + + "' already exists in this VO."); return cert; } @@ -634,12 +580,10 @@ public VOMSUser create(VOMSUser usr, String caDN) { usr.addCertificate(cert); - HibernateFactory.getSession() - .save(usr); + HibernateFactory.getSession().save(usr); // Add user to VO root group - VOMSGroup voGroup = VOMSGroupDAO.instance() - .getVOGroup(); + VOMSGroup voGroup = VOMSGroupDAO.instance().getVOGroup(); usr.addToGroup(voGroup); return usr; @@ -652,22 +596,20 @@ public VOMSUser create(VOMSUser usr) { } - public VOMSUserAttribute createAttribute(VOMSUser u, String attrName, - String attrDesc, String value) { + public VOMSUserAttribute createAttribute(VOMSUser u, String attrName, String attrDesc, + String value) { if (u.getAttributeByName(attrName) != null) - throw new AttributeAlreadyExistsException("Attribute \"" + attrName - + "\" already defined for user \"" + u + "\"."); + throw new AttributeAlreadyExistsException( + "Attribute \"" + attrName + "\" already defined for user \"" + u + "\"."); - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); if (desc == null) - desc = VOMSAttributeDAO.instance() - .createAttributeDescription(attrName, attrDesc); + desc = VOMSAttributeDAO.instance().createAttributeDescription(attrName, attrDesc); - log.debug("Creating attribute \"(" + attrName + "," + value - + ")\" for user \"" + u + "\"."); + log.debug("Creating attribute \"(" + attrName + "," + value + ")\" for user \"" + u + "\"."); VOMSUserAttribute val = VOMSUserAttribute.instance(desc, value, u); u.addAttribute(val); return val; @@ -679,8 +621,7 @@ public VOMSUser delete(Long userId) { VOMSUser u = findById(userId); if (u == null) - throw new NoSuchUserException( - "User identified by \"" + userId + "\" not found in database!"); + throw new NoSuchUserException("User identified by \"" + userId + "\" not found in database!"); try { @@ -690,8 +631,7 @@ public VOMSUser delete(Long userId) { } catch (ObjectNotFoundException e) { // Still don't understand why sometimes findById fails in returnin // null... - throw new NoSuchUserException( - "User identified by \"" + userId + "\" not found in database!"); + throw new NoSuchUserException("User identified by \"" + userId + "\" not found in database!"); } } @@ -699,24 +639,16 @@ public VOMSUser delete(VOMSUser u) { log.debug("Deleting user \"{}\"", u); - DAOFactory.instance() - .getRequestDAO() - .deleteRequestFromUser(u); + DAOFactory.instance().getRequestDAO().deleteRequestFromUser(u); - u.getCertificates() - .clear(); + u.getCertificates().clear(); u.cleanMappings(); - u.getAttributes() - .clear(); - u.getAupAcceptanceRecords() - .clear(); - u.getPersonalInformations() - .clear(); - u.getTasks() - .clear(); - - HibernateFactory.getSession() - .delete(u); + u.getAttributes().clear(); + u.getAupAcceptanceRecords().clear(); + u.getPersonalInformations().clear(); + u.getTasks().clear(); + + HibernateFactory.getSession().delete(u); return u; @@ -738,14 +670,13 @@ public VOMSUserAttribute deleteAttribute(VOMSUser u, String attrName) { if (attribute == null) { throw new NoSuchAttributeException( - "Attribute \"" + attrName + "\" not defined for user \"" + u + "\"."); + "Attribute \"" + attrName + "\" not defined for user \"" + u + "\"."); } log.debug("Deleting attribute \"{}\" for user \"{}\".", attrName, u); u.deleteAttribute(attribute); - HibernateFactory.getSession() - .update(u); + HibernateFactory.getSession().update(u); return attribute; } @@ -763,18 +694,15 @@ public void deleteCertificate(VOMSUser u, Certificate cert) { Validate.notNull(u, "Please provide a non-null user."); Validate.notNull(cert, "Cannot delete a null certificate."); - if (u.getCertificates() - .size() == 1 && u.hasCertificate(cert)) - throw new VOMSException( - "User has only one certificate registered, so it cannot be removed!"); + if (u.getCertificates().size() == 1 && u.hasCertificate(cert)) + throw new VOMSException("User has only one certificate registered, so it cannot be removed!"); - if (!u.getCertificates() - .remove(cert)) { + if (!u.getCertificates().remove(cert)) { // This should never happen throw new VOMSDatabaseException( - "Inconsistent database! It was not possible to remove certificate '" - + cert + "' from user '" + u - + "', even if it seemed user actually possessed such certificate."); + "Inconsistent database! It was not possible to remove certificate '" + cert + + "' from user '" + u + + "', even if it seemed user actually possessed such certificate."); } } @@ -782,8 +710,7 @@ public void deleteCertificate(VOMSUser u, Certificate cert) { public void dismissRole(VOMSUser u, VOMSGroup g, VOMSRole r) { u.dismissRole(g, r); - HibernateFactory.getSession() - .update(u); + HibernateFactory.getSession().update(u); } @@ -791,13 +718,13 @@ public VOMSUser findBySubject(String subject) { if (subject == null) throw new NullArgumentException("subject cannot be null!"); - + String normalizedSubject = DNUtil.normalizeDN(subject); - String query = "select u from org.glite.security.voms.admin.persistence.model.VOMSUser u join u.certificates c where c.subjectString = :subjectString"; + String query = + "select u from org.glite.security.voms.admin.persistence.model.VOMSUser u join u.certificates c where c.subjectString = :subjectString"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); q.setString("subjectString", normalizedSubject); @@ -820,10 +747,10 @@ public VOMSUser findBySubjectAndIssuer(String subject, String issuer) { String normalizedSubject = DNUtil.normalizeDN(subject); String normalizedIssuer = DNUtil.normalizeDN(issuer); - String query = "select u from VOMSUser u join u.certificates c where c.subjectString = :subjectString and c.ca.subjectString = :issuerSubjectString"; + String query = + "select u from VOMSUser u join u.certificates c where c.subjectString = :subjectString and c.ca.subjectString = :issuerSubjectString"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); q.setString("subjectString", normalizedSubject); q.setString("issuerSubjectString", normalizedIssuer); @@ -838,9 +765,9 @@ public VOMSUser findByEmail(String emailAddress) { if (emailAddress == null) throw new NullArgumentException("emailAddress must be non-null!"); - String query = "from org.glite.security.voms.admin.persistence.model.VOMSUser as u where u.emailAddress = :emailAddress"; - Query q = HibernateFactory.getSession() - .createQuery(query); + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSUser as u where u.emailAddress = :emailAddress"; + Query q = HibernateFactory.getSession().createQuery(query); q.setString("emailAddress", emailAddress); @@ -850,28 +777,25 @@ public VOMSUser findByEmail(String emailAddress) { public VOMSUser findById(Long userId) { - return (VOMSUser) HibernateFactory.getSession() - .get(VOMSUser.class, userId); + return (VOMSUser) HibernateFactory.getSession().get(VOMSUser.class, userId); } public List findByOrgdbId(Long orgdbId) { - CriteriaBuilder builder = HibernateFactory - .getSession().getCriteriaBuilder(); - + CriteriaBuilder builder = HibernateFactory.getSession().getCriteriaBuilder(); + CriteriaQuery query = builder.createQuery(VOMSUser.class); Root userRoot = query.from(VOMSUser.class); query.where(builder.equal(userRoot.get("orgDbId"), orgdbId)); - + return HibernateFactory.getSession().createQuery(query).getResultList(); } - + public ScrollableResults findAllWithCursor() { Query q = HibernateFactory.getSession() .createQuery("select u from VOMSUser u order by u.surname asc"); - q.setCacheMode(CacheMode.IGNORE) - .scroll(ScrollMode.FORWARD_ONLY); + q.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); return q.scroll(); @@ -888,8 +812,8 @@ public List findAll() { return result; } - private SearchResults paginatedFind(Query q, Query countQuery, - String searchString, int firstResults, int maxResults) { + private SearchResults paginatedFind(Query q, Query countQuery, String searchString, + int firstResults, int maxResults) { SearchResults res = SearchResults.instance(); @@ -915,13 +839,11 @@ private String getUserOrderClause() { // If endTime is ignored by configuration, we should not consider // it for sorting the search results boolean endTimeDisabled = VOMSConfiguration.instance() - .getBoolean(VOMSConfigurationConstants.DISABLE_MEMBERSHIP_END_TIME, - false); + .getBoolean(VOMSConfigurationConstants.DISABLE_MEMBERSHIP_END_TIME, false); - if (endTimeDisabled){ + if (endTimeDisabled) { return "order by u.surname asc"; - } - else { + } else { return "order by u.endTime asc, u.surname asc"; } } @@ -930,11 +852,9 @@ public SearchResults findAll(int firstResults, int maxResults) { String query = "from VOMSUser as u " + getUserOrderClause(); - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); - Query countQ = HibernateFactory.getSession() - .createQuery("select count(*) from VOMSUser"); + Query countQ = HibernateFactory.getSession().createQuery("select count(*) from VOMSUser"); return paginatedFind(q, countQ, null, firstResults, maxResults); } @@ -943,33 +863,29 @@ public List getUnAssignedRoles(Long userId, Long groupId) { VOMSUser u = findById(userId); - VOMSGroup g = VOMSGroupDAO.instance() - .findById(groupId); + VOMSGroup g = VOMSGroupDAO.instance().findById(groupId); String query = "from VOMSRole r where r not in " - + "(select m.role from VOMSMapping m where m.user = :user " - + "and m.group = :group and m.role is not null)"; - - Query hq = - HibernateFactory.getSession().createQuery(query, VOMSRole.class); - hq.setParameter("user", u); - hq.setParameter("group", g); - + + "(select m.role from VOMSMapping m where m.user = :user " + + "and m.group = :group and m.role is not null)"; + + Query hq = HibernateFactory.getSession().createQuery(query, VOMSRole.class); + hq.setParameter("user", u); + hq.setParameter("group", g); + List result = hq.getResultList(); return result; } public List getUnsubscribedGroups(Long userId) { - + VOMSUser u = findById(userId); - + String query = "from VOMSGroup g where g not in " - + "(select m.group from VOMSMapping m where m.user = :user " - + "and m.role is null)"; - - Query hq = - HibernateFactory.getSession().createQuery(query, VOMSGroup.class); + + "(select m.group from VOMSMapping m where m.user = :user " + "and m.role is null)"; + + Query hq = HibernateFactory.getSession().createQuery(query, VOMSGroup.class); hq.setParameter("user", u); List result = hq.getResultList(); return result; @@ -979,10 +895,8 @@ public void removeFromGroup(VOMSUser u, VOMSGroup g) { log.debug("Removing user \"" + u + "\" from group \"" + g + "\"."); - if (VOMSGroupDAO.instance() - .findByName(g.getName()) == null) - throw new NoSuchGroupException( - "Group \"" + g + "\" is not defined in database."); + if (VOMSGroupDAO.instance().findByName(g.getName()) == null) + throw new NoSuchGroupException("Group \"" + g + "\" is not defined in database."); u.removeFromGroup(g); @@ -992,8 +906,7 @@ public void removeFromGroup(VOMSUser u, VOMSGroup g) { public List findSuspendedUsers() { String queryString = "from VOMSUser u where u.suspended = true"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); return q.list(); } @@ -1002,8 +915,7 @@ public List findSuspendedUsers() { public List findSuspendedUsers(int firstResult, int maxResults) { String queryString = "from VOMSUser u where u.suspended = true"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); return q.list(); } @@ -1011,35 +923,32 @@ public List findSuspendedUsers(int firstResult, int maxResults) { public Long countSuspendedUsers() { String queryString = "select count(*) from VOMSUser u where u.suspended = true"; - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); return (Long) q.uniqueResult(); } - public SearchResults searchExpired(String searchString, int firstResults, - int maxResults) { + public SearchResults searchExpired(String searchString, int firstResults, int maxResults) { - log.debug("searchString:" + searchString + ",firstResults: " + firstResults - + ",maxResults: " + maxResults); + log.debug("searchString:" + searchString + ",firstResults: " + firstResults + ",maxResults: " + + maxResults); - if (searchString == null || searchString.trim() - .equals("") || searchString.length() == 0) + if (searchString == null || searchString.trim().equals("") || searchString.length() == 0) return findAll(firstResults, maxResults); SearchResults res = SearchResults.instance(); String sString = "%" + searchString + "%"; - String queryString = "select distinct u from VOMSUser u join u.certificates as cert where u.expired = true and (lower(u.surname) like lower(:searchString) " - + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " - + " or lower(u.institution) like lower(:searchString) " - + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString))" - + getUserOrderClause(); + String queryString = + "select distinct u from VOMSUser u join u.certificates as cert where u.expired = true and (lower(u.surname) like lower(:searchString) " + + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " + + " or lower(u.institution) like lower(:searchString) " + + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString))" + + getUserOrderClause(); - Query q = HibernateFactory.getSession() - .createQuery(queryString); + Query q = HibernateFactory.getSession().createQuery(queryString); q.setString("searchString", sString); q.setFirstResult(firstResults); @@ -1054,49 +963,40 @@ public SearchResults searchExpired(String searchString, int firstResults, return res; } - public SearchResults searchWithPendingAUPRequest(String searchString, - int firstResults, int maxResults) { + public SearchResults searchWithPendingAUPRequest(String searchString, int firstResults, + int maxResults) { - AUP aup = DAOFactory.instance() - .getAUPDAO() - .getVOAUP(); + AUP aup = DAOFactory.instance().getAUPDAO().getVOAUP(); String queryString = "from VOMSUser u join u.tasks as t join u.certificates as cert " - + "where t.class = SignAUPTask and t.status != 'COMPLETED' " - + "and t.aup = :aup"; + + "where t.class = SignAUPTask and t.status != 'COMPLETED' " + "and t.aup = :aup"; String commonSearchString = "and (lower(u.surname) like lower(:searchString) " - + "or lower(u.name) like lower(:searchString) " - + "or u.emailAddress like :searchString " - + "or lower(u.institution) like lower(:searchString) " - + "or cert.subjectString like(:searchString) " - + "or cert.ca.subjectString like(:searchString))"; + + "or lower(u.name) like lower(:searchString) " + "or u.emailAddress like :searchString " + + "or lower(u.institution) like lower(:searchString) " + + "or cert.subjectString like(:searchString) " + + "or cert.ca.subjectString like(:searchString))"; if (searchStringEmpty(searchString)) { - Query q = HibernateFactory.getSession() - .createQuery("select distinct u " + queryString) - .setEntity("aup", aup); + Query q = + HibernateFactory.getSession().createQuery("select distinct u " + queryString).setEntity( + "aup", aup); - String countQuery = String.format("select count(distinct u) %s", - queryString); - Query countQ = HibernateFactory.getSession() - .createQuery(countQuery) - .setEntity("aup", aup); + String countQuery = String.format("select count(distinct u) %s", queryString); + Query countQ = HibernateFactory.getSession().createQuery(countQuery).setEntity("aup", aup); return paginatedFind(q, countQ, null, firstResults, maxResults); } else { String sString = "%" + searchString + "%"; - String commonQueryPart = String.format("%s %s", queryString, - commonSearchString); + String commonQueryPart = String.format("%s %s", queryString, commonSearchString); Query q = HibernateFactory.getSession() .createQuery(String.format("select distinct u %s", commonQueryPart)) .setEntity("aup", aup); Query count = HibernateFactory.getSession() - .createQuery( - String.format("select count(distinct u) %s", commonQueryPart)) + .createQuery(String.format("select count(distinct u) %s", commonQueryPart)) .setEntity("aup", aup); q.setString("searchString", sString); @@ -1107,16 +1007,14 @@ public SearchResults searchWithPendingAUPRequest(String searchString, } - public SearchResults searchSuspended(String searchString, int firstResults, - int maxResults) { + public SearchResults searchSuspended(String searchString, int firstResults, int maxResults) { if (searchStringEmpty(searchString)) { - Query q = HibernateFactory.getSession() - .createQuery("from VOMSUser u where u.suspended = true"); + Query q = + HibernateFactory.getSession().createQuery("from VOMSUser u where u.suspended = true"); Query countQ = HibernateFactory.getSession() - .createQuery( - "select count(*) from VOMSUser u where u.suspended = true"); + .createQuery("select count(*) from VOMSUser u where u.suspended = true"); return paginatedFind(q, countQ, null, firstResults, maxResults); @@ -1124,11 +1022,12 @@ public SearchResults searchSuspended(String searchString, int firstResults, String sString = "%" + searchString + "%"; - String commonQueryPart = "from VOMSUser u join u.certificates as cert where u.suspended = true and (lower(u.surname) like lower(:searchString) " - + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " - + " or lower(u.institution) like lower(:searchString) " - + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString))" - + getUserOrderClause(); + String commonQueryPart = + "from VOMSUser u join u.certificates as cert where u.suspended = true and (lower(u.surname) like lower(:searchString) " + + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " + + " or lower(u.institution) like lower(:searchString) " + + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString))" + + getUserOrderClause(); // FIXME: this is *UGLY*, use Criteria API instead Query q = HibernateFactory.getSession() @@ -1147,32 +1046,31 @@ public SearchResults searchSuspended(String searchString, int firstResults, private boolean searchStringEmpty(String searchString) { - return (searchString == null || searchString.trim() - .equals("") || searchString.length() == 0); + return (searchString == null || searchString.trim().equals("") || searchString.length() == 0); } - public SearchResults search(String searchString, int firstResults, - int maxResults) { + public SearchResults search(String searchString, int firstResults, int maxResults) { - log.debug("searchString:" + searchString + ",firstResults: " + firstResults - + ",maxResults: " + maxResults); + log.debug("searchString:" + searchString + ",firstResults: " + firstResults + ",maxResults: " + + maxResults); if (searchStringEmpty(searchString)) return findAll(firstResults, maxResults); String sString = "%" + searchString + "%"; - String commonPart = "from VOMSUser u join u.certificates as cert where lower(u.surname) like lower(:searchString) " - + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " - + " or lower(u.institution) like lower(:searchString) " - + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString) " - + getUserOrderClause(); + String commonPart = + "from VOMSUser u join u.certificates as cert where lower(u.surname) like lower(:searchString) " + + "or lower(u.name) like lower(:searchString) or u.emailAddress like :searchString " + + " or lower(u.institution) like lower(:searchString) " + + " or cert.subjectString like(:searchString) or cert.ca.subjectString like(:searchString) " + + getUserOrderClause(); Query q = HibernateFactory.getSession() .createQuery(String.format("select distinct u %s", commonPart)); - Query count = HibernateFactory.getSession() - .createQuery(String.format("select count(*) %s", commonPart)); + Query count = + HibernateFactory.getSession().createQuery(String.format("select count(*) %s", commonPart)); q.setString("searchString", sString); count.setString("searchString", sString); @@ -1181,20 +1079,17 @@ public SearchResults search(String searchString, int firstResults, } - public VOMSUserAttribute setAttribute(VOMSUser u, String attrName, - String attrValue) { + public VOMSUserAttribute setAttribute(VOMSUser u, String attrName, String attrValue) { - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); log.debug("AttributeDescription:" + desc); if (desc == null) - throw new NoSuchAttributeException( - "Attribute '" + attrName + "' is not defined in this vo."); + throw new NoSuchAttributeException("Attribute '" + attrName + "' is not defined in this vo."); - if (!VOMSAttributeDAO.instance() - .isAttributeValueAlreadyAssigned(u, desc, attrValue)) { + if (!VOMSAttributeDAO.instance().isAttributeValueAlreadyAssigned(u, desc, attrValue)) { VOMSUserAttribute val = u.getAttributeByName(desc.getName()); if (val == null) { @@ -1206,24 +1101,24 @@ public VOMSUserAttribute setAttribute(VOMSUser u, String attrName, return val; } - throw new AttributeValueAlreadyAssignedException("Value '" + attrValue - + "' for attribute '" + attrName - + "' has been already assigned to another user in this vo! Choose a different value."); + throw new AttributeValueAlreadyAssignedException( + "Value '" + attrValue + "' for attribute '" + attrName + + "' has been already assigned to another user in this vo! Choose a different value."); } public VOMSUser update(VOMSUser u) { - HibernateFactory.getSession() - .update(u); + HibernateFactory.getSession().update(u); return u; } public Long countExpiringUsers(Integer intervalInDays) { - Criteria crit = HibernateFactory.getSession() - .createCriteria(VOMSUser.class); + String query = + "select count(distinct u) from VOMSUser u where u.endTime between :startDate AND :endDate " + + "and suspended is false order by u.endTime asc"; Calendar cal = Calendar.getInstance(); @@ -1231,23 +1126,18 @@ public Long countExpiringUsers(Integer intervalInDays) { cal.add(Calendar.DAY_OF_YEAR, intervalInDays); Date intervalDate = cal.getTime(); + + Query q = HibernateFactory.getSession() + .createQuery(query); - crit.add(Restrictions.between("endTime", now, intervalDate)); - crit.add(Restrictions.eq("suspended", false)); - - crit.setProjection(Projections.rowCount()); - - return (Long) crit.list() - .get(0); - + q.setDate("startDate", now); + q.setDate("endDate", intervalDate); + return (Long) q.getSingleResult(); } @SuppressWarnings("unchecked") public List findExpiringUsers(Integer intervalInDays) { - - Criteria crit = HibernateFactory.getSession() - .createCriteria(VOMSUser.class); - + Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); @@ -1255,19 +1145,23 @@ public List findExpiringUsers(Integer intervalInDays) { Date intervalDate = cal.getTime(); - crit.add(Restrictions.between("endTime", now, intervalDate)); - crit.add(Restrictions.eq("suspended", false)); - crit.addOrder(Order.asc("endTime")); + String query = + "select distinct u from VOMSUser u where u.endTime between :startDate AND :endDate " + + "and suspended is false order by u.endTime asc"; - return crit.list(); + Query q = HibernateFactory.getSession() + .createQuery(query); + + q.setDate("startDate", now); + q.setDate("endDate", intervalDate); + return q.list(); } public VOMSUser lookup(String certificateSubject, String certificateIssuer) { - return LookupPolicyProvider.instance() - .lookupStrategy() - .lookup(this, certificateSubject, certificateIssuer); + return LookupPolicyProvider.instance().lookupStrategy().lookup(this, certificateSubject, + certificateIssuer); } diff --git a/voms-admin-server/src/main/resources/templates/ExpiredMembersWarning.vm b/voms-admin-server/src/main/resources/templates/ExpiredMembersWarning.vm index eeab0443..5df31802 100644 --- a/voms-admin-server/src/main/resources/templates/ExpiredMembersWarning.vm +++ b/voms-admin-server/src/main/resources/templates/ExpiredMembersWarning.vm @@ -19,9 +19,11 @@ this mail is to inform you that membership in VO $voName for the following users #foreach ( $member in $expiredMembers) -$member.shortName membership has expired since $member.daysSinceExpiration days.#if ($member.suspended) The user membership is currently suspended.#else -The user is still active can get VOMS attributes as usual. - +$member.shortName membership has expired since $member.daysSinceExpiration days. +#if ($member.suspended) +$member.shortName membership is currently suspended. +#else +$member.shortName is still active and can get VOMS attributes as usual. #end #end diff --git a/voms-admin-server/src/main/resources/templates/MembershipExpirationWarning.vm b/voms-admin-server/src/main/resources/templates/MembershipExpirationWarning.vm index 8270b342..81ad539e 100644 --- a/voms-admin-server/src/main/resources/templates/MembershipExpirationWarning.vm +++ b/voms-admin-server/src/main/resources/templates/MembershipExpirationWarning.vm @@ -19,7 +19,9 @@ this mail is to inform you that membership in VO $voName for the following users TO EXPIRE: #foreach ( $user in $expiringUsers) -#if ($user.daysBeforeEndTime > 0) +#if ($user.daysBeforeEndTime == 0) +$user.shortName membership will expire in the next 24 hours +#elseif ($user.daysBeforeEndTime > 0) $user.shortName membership will expire in $user.daysBeforeEndTime days. #end #end diff --git a/voms-admin-server/src/main/webapp/style/badge.css b/voms-admin-server/src/main/webapp/style/badge.css index b6a76d6b..59610430 100644 --- a/voms-admin-server/src/main/webapp/style/badge.css +++ b/voms-admin-server/src/main/webapp/style/badge.css @@ -97,14 +97,15 @@ color: #B94A48; font-weight: normal; text-shadow: none; + padding: 0; } .blabel-invert { - background-color: inherit; color: inherit; font-weight: normal; text-shadow: none; + padding: 0; } .blabel-invert:hover { From 86da54411ea22b98364cd327101e403e2f152600 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 9 May 2018 11:07:07 +0200 Subject: [PATCH 20/63] Jenkinsfile: fix syntax --- Jenkinsfile | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e476d3fd..7df2e828 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,8 +13,10 @@ pipeline { stage('build') { steps { - git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) - sh 'mvn -B -U -P prod,EMI clean package' + container('maven-runner') { + git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) + sh 'mvn -B -U -P prod,EMI clean package' + } } } @@ -24,13 +26,15 @@ pipeline { expression { return params.BUILD_DOCKER_IMAGES } } steps { - sh ''' - pushd docker/voms-admin-server - sh build-image.sh && sh push-image.sh - popd - push docker/voms/centos6 - sh build-image.sh && sh push-image.sh - popd''' + container('docker-runner') { + sh ''' + pushd docker/voms-admin-server + sh build-image.sh && sh push-image.sh + popd + push docker/voms/centos6 + sh build-image.sh && sh push-image.sh + popd''' + } } } } From 3666af28379a00d296ae48da1e0d087c14d53f8d Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 10 May 2018 15:01:09 +0200 Subject: [PATCH 21/63] Fixed license headers --- .../voms/admin/persistence/dao/VOMSUserDAO.java | 16 +++++++++------- .../AuditLogSearchParams-conversion.properties | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index e125dc42..a00483cd 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.persistence.dao; diff --git a/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties index 55318c43..860207df 100644 --- a/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties +++ b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties @@ -1,2 +1,18 @@ +# +# Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + fromTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter toTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter From f3bfa157035458ecfbd35857aedf2b8c045b6ed1 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 21 May 2018 18:04:21 +0200 Subject: [PATCH 22/63] Fix user search results count query The user search results count counted rows multiple times when multiple joined entities were returned (e.g. when a user has multiple certificates linked to his membership). This commit fixes that issue. Issue: https://issues.infn.it/jira/browse/VOMS-693 --- .../glite/security/voms/admin/persistence/dao/VOMSUserDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index eaf1c6e7..ae74a89d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -1172,7 +1172,7 @@ public SearchResults search(String searchString, int firstResults, Query q = HibernateFactory.getSession() .createQuery(String.format("select distinct u %s", commonPart)); Query count = HibernateFactory.getSession() - .createQuery(String.format("select count(*) %s", commonPart)); + .createQuery(String.format("select count(distinct u) %s", commonPart)); q.setString("searchString", sString); count.setString("searchString", sString); From f0ee6698160efccaa45009394c3eb59fb53ba2cf Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 21 May 2018 18:46:34 +0200 Subject: [PATCH 23/63] Add missing license --- .../AuditLogSearchParams-conversion.properties | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties index 55318c43..860207df 100644 --- a/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties +++ b/voms-admin-server/src/main/resources/org/glite/security/voms/admin/view/actions/audit/AuditLogSearchParams-conversion.properties @@ -1,2 +1,18 @@ +# +# Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + fromTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter toTime=org.glite.security.voms.admin.view.util.FixedLocaleDateTypeConverter From 9b62906d9b0cbea18a37befdd9cba89438a3a067 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 21 May 2018 19:38:58 +0200 Subject: [PATCH 24/63] Fix bulk extend membership behaviour Bulk extend membership button behaviour was broken in a recent update. Clicking the button triggered the user restore bulk operation. This commit provides a fix to such problem. Issue: https://issues.infn.it/jira/browse/VOMS-836 --- .../src/main/webapp/WEB-INF/p/shared/dialogs.jsp | 9 +++++++++ .../src/main/webapp/WEB-INF/p/user/users.jsp | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/shared/dialogs.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/shared/dialogs.jsp index 67e4ce5c..7fa07026 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/shared/dialogs.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/shared/dialogs.jsp @@ -76,6 +76,15 @@ + +
@@ -138,7 +139,10 @@ action="bulk-extend-membership-expiration" theme="simple" cssClass="userActionButton" - disabled="%{#attr.canSuspend == false}" /> + disabled="%{#attr.canSuspend == false}" + onclick="openConfirmDialog(this, 'extendMembershipMultiDialog', ''); return false" + + /> Date: Mon, 21 May 2018 19:50:27 +0200 Subject: [PATCH 25/63] Added missing license --- .../util/validation/x509/CanlDNValidator.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java index 4fd838db..8a099be4 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/validation/x509/CanlDNValidator.java @@ -1,15 +1,17 @@ /** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.glite.security.voms.admin.util.validation.x509; From 88374e1f4d564d6e6140630d2c925ec3253befdb Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 22 May 2018 17:05:09 +0200 Subject: [PATCH 26/63] Bumped version to 3.7.1 --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 2 +- voms-container/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8b056bd4..876fbd47 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.7.1 pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index d000a0d5..5e6e6e41 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.7.1 voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index a8d16c09..f8c863c2 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -24,7 +24,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.7.1 voms-admin-server diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 23055ce7..74401ad7 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.7.1 voms-container From 44287efbb676a726d1e253e0440771f235f874bc Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 22 May 2018 17:19:18 +0200 Subject: [PATCH 27/63] Bumped version to 3.8.0-SNAPSHOT --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 2 +- voms-container/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8b056bd4..6429e505 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.8.0-SNAPSHOT pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index d000a0d5..dc7183bf 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.8.0-SNAPSHOT voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index a8d16c09..90f7c3cd 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -24,7 +24,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.8.0-SNAPSHOT voms-admin-server diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 23055ce7..2c5909e5 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.7.1-SNAPSHOT + 3.8.0-SNAPSHOT voms-container From b396281e28a03a588ab38a25deb7925bf4c580b7 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 23 Aug 2018 12:43:02 +0200 Subject: [PATCH 28/63] Bump struts version to 2.3.35 --- voms-admin-server/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index f8c863c2..51b64f04 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -36,7 +36,7 @@ ${project.version} 2.0.2 - 2.3.34 + 2.3.35 2.0.1 3.7.1 5.2.8.Final From 69c977451b138be33bef1fd7aa3d34b1b7663095 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 7 Nov 2018 11:58:31 +0100 Subject: [PATCH 29/63] Use hostname -f in info-providers --- .../scripts/info-providers/voms-config-info-providers.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voms-admin-server/resources/scripts/info-providers/voms-config-info-providers.sh b/voms-admin-server/resources/scripts/info-providers/voms-config-info-providers.sh index f4dc5c46..1818c27d 100644 --- a/voms-admin-server/resources/scripts/info-providers/voms-config-info-providers.sh +++ b/voms-admin-server/resources/scripts/info-providers/voms-config-info-providers.sh @@ -18,7 +18,7 @@ # determine the hostname -SERVICE_HOST=`hostname` +SERVICE_HOST=$(hostname -f) # configuration template INFO_PROVIDER_CONF_TEMPLATE_DIR="/usr/share/voms-admin/info-providers" From 11907d605f992f51465607bfffbf6c2be94f0f01 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 7 Nov 2018 12:05:29 +0100 Subject: [PATCH 30/63] trigger daily build --- Jenkinsfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 7df2e828..eb5af759 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,9 +1,13 @@ pipeline { agent { label 'maven' } + parameters { booleanParam(name: 'BUILD_DOCKER_IMAGES', defaultValue: false, description: 'Triggers the building of docker images required for development') } + + triggers { cron('@daily') } + options { timeout(time: 1, unit: 'HOURS') buildDiscarder(logRotator(numToKeepStr: '5')) From f29d2a712527d8413d83ced21e9628f56feda46c Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 21 Jun 2019 15:41:11 +0200 Subject: [PATCH 31/63] Updated CI configuration --- Jenkinsfile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index eb5af759..949540a7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,12 @@ pipeline { - agent { label 'maven' } + agent { + kubernetes { + label "voms-admin-server-${env.JOB_BASE_NAME}-${env.BUILD_NUMBER}" + cloud 'Kube mwdevel' + defaultContainer 'jnlp' + inheritFrom 'ci-template' + } + } parameters { booleanParam(name: 'BUILD_DOCKER_IMAGES', defaultValue: false, @@ -17,7 +24,7 @@ pipeline { stage('build') { steps { - container('maven-runner') { + container('runner') { git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) sh 'mvn -B -U -P prod,EMI clean package' } @@ -30,7 +37,7 @@ pipeline { expression { return params.BUILD_DOCKER_IMAGES } } steps { - container('docker-runner') { + container('runner') { sh ''' pushd docker/voms-admin-server sh build-image.sh && sh push-image.sh From abdc00f2bb96b60e7e7e95fa7def192f686da052 Mon Sep 17 00:00:00 2001 From: enricovianello Date: Thu, 27 Jun 2019 18:45:09 +0200 Subject: [PATCH 32/63] Adapted Jenkinsfile to latest ci changes --- Jenkinsfile | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 949540a7..7555af91 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,11 +1,15 @@ +@Library('sd')_ +def kubeLabel = getKubeLabel() + pipeline { + agent { - kubernetes { - label "voms-admin-server-${env.JOB_BASE_NAME}-${env.BUILD_NUMBER}" - cloud 'Kube mwdevel' - defaultContainer 'jnlp' - inheritFrom 'ci-template' - } + kubernetes { + label "${kubeLabel}" + cloud 'Kube mwdevel' + defaultContainer 'runner' + inheritFrom 'ci-template' + } } parameters { @@ -24,28 +28,23 @@ pipeline { stage('build') { steps { - container('runner') { - git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) - sh 'mvn -B -U -P prod,EMI clean package' - } + git(url: 'https://github.com/italiangrid/voms-admin-server.git', branch: env.BRANCH_NAME) + sh 'mvn -B -U -P prod,EMI clean package' } } stage('build-docker-images') { - agent { label 'docker' } when { expression { return params.BUILD_DOCKER_IMAGES } } steps { - container('runner') { - sh ''' - pushd docker/voms-admin-server - sh build-image.sh && sh push-image.sh - popd - push docker/voms/centos6 - sh build-image.sh && sh push-image.sh - popd''' - } + sh ''' + pushd docker/voms-admin-server + sh build-image.sh && sh push-image.sh + popd + push docker/voms/centos6 + sh build-image.sh && sh push-image.sh + popd''' } } } From 8dafba8715c52860f998ca85b4a0faeedcb05407 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 27 Nov 2019 06:57:00 +0100 Subject: [PATCH 33/63] Dependency updates --- .env | 1 + pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 8 ++++---- voms-container/pom.xml | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..37764862 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=voms diff --git a/pom.xml b/pom.xml index 876fbd47..6429e505 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.7.1 + 3.8.0-SNAPSHOT pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index 5e6e6e41..dc7183bf 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.7.1 + 3.8.0-SNAPSHOT voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 51b64f04..815a0aeb 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -24,7 +24,7 @@ org.italiangrid voms-admin-parent - 3.7.1 + 3.8.0-SNAPSHOT voms-admin-server @@ -36,11 +36,11 @@ ${project.version} 2.0.2 - 2.3.35 + 2.3.37 2.0.1 3.7.1 - 5.2.8.Final - 0.9.5.2 + 5.2.17.Final + 0.9.5.4 2.5.3 2.2.2 3.2 diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 74401ad7..2c5909e5 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.7.1 + 3.8.0-SNAPSHOT voms-container From c01bf3a6210c062f263d4233334befeb13dbc6f1 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 28 Nov 2019 19:51:30 +0100 Subject: [PATCH 34/63] First incarnation of new HR db integration code --- docker-compose.yml | 2 +- pom.xml | 4 +- voms-admin-api/src/main/resources/rebel.xml | 12 - voms-admin-server/pom.xml | 15 + .../configuration/VOMSConfiguration.java | 2 +- .../AbstractPluginConfigurator.java | 21 +- .../voms/admin/integration/PluginManager.java | 6 +- .../admin/integration/cern/DateUtils.java | 34 ++ .../cern/DefaultHrDbSyncTaskFactory.java | 53 +++ .../integration/cern/HrDbApiService.java | 37 +++ .../cern/HrDbApiServiceFactory.java | 23 ++ .../integration/cern/HrDbConfigurator.java | 212 ++++++++++++ .../admin/integration/cern/HrDbError.java | 36 +++ .../integration/cern/HrDbProperties.java | 208 ++++++++++++ .../cern/HrDbRequestValidator.java | 121 +++++++ .../cern/HrDbRequestValidatorFactory.java | 20 ++ .../admin/integration/cern/HrDbSyncTask.java | 91 ++++++ .../integration/cern/HrDbSyncTaskFactory.java | 24 ++ .../integration/cern/HrDefaultHandler.java | 110 +++++++ .../cern/HttpClientHrDbApiService.java | 196 +++++++++++ .../cern/HttpClientHrDbApiServiceFactory.java | 28 ++ .../admin/integration/cern/dto/ErrorDTO.java | 49 +++ .../integration/cern/dto/InstituteDTO.java | 82 +++++ .../integration/cern/dto/ListResponseDTO.java | 85 +++++ .../cern/dto/ParticipationDTO.java | 100 ++++++ .../integration/cern/dto/VOPersonDTO.java | 219 +++++++++++++ .../ExpiredParticipationStrategy.java | 24 ++ .../MembershipSynchronizationStrategy.java | 26 ++ .../MissingMembershipRecordStrategy.java | 22 ++ .../integration/orgdb/OrgDBConfigurator.java | 4 + .../admin/persistence/model/VOMSUser.java | 209 +++++------- .../src/main/resources/rebel.xml | 19 -- .../integration/hr/HrDbConfiguratorTests.java | 200 ++++++++++++ .../integration/hr/HrDbPropertiesTest.java | 92 ++++++ .../hr/HrDbRequestValidatorTest.java | 144 +++++++++ .../java/integration/hr/HrDbSyncTaskTest.java | 143 +++++++++ .../java/integration/hr/HrDbTestSupport.java | 44 +++ .../integration/hr/HrDefaultHandlerTest.java | 214 +++++++++++++ .../hr/HttpClientIntegrationTest.java | 303 ++++++++++++++++++ .../src/test/java/utils/TestFileUtils.java | 36 +++ .../src/test/java/utils/TestSocketUtils.java | 36 +++ .../resources/cern/config/orgdb.properties | 7 + .../test/resources/cern/json/voPerson1.json | 20 ++ voms-container/src/main/resources/rebel.xml | 9 - 44 files changed, 3157 insertions(+), 185 deletions(-) delete mode 100644 voms-admin-api/src/main/resources/rebel.xml create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DateUtils.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DefaultHrDbSyncTaskFactory.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiService.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiServiceFactory.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbError.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidatorFactory.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTaskFactory.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiServiceFactory.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/InstituteDTO.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ListResponseDTO.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ParticipationDTO.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/ExpiredParticipationStrategy.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MembershipSynchronizationStrategy.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MissingMembershipRecordStrategy.java delete mode 100644 voms-admin-server/src/main/resources/rebel.xml create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDbSyncTaskTest.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java create mode 100644 voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java create mode 100644 voms-admin-server/src/test/java/utils/TestFileUtils.java create mode 100644 voms-admin-server/src/test/java/utils/TestSocketUtils.java create mode 100644 voms-admin-server/src/test/resources/cern/config/orgdb.properties create mode 100644 voms-admin-server/src/test/resources/cern/json/voPerson1.json delete mode 100644 voms-container/src/main/resources/rebel.xml diff --git a/docker-compose.yml b/docker-compose.yml index 71179791..ba1bea30 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,7 @@ services: # - "6002:6002" # 1044 is the debug port - "1044:1044" - - "8443" + - "8443:8443" links: - db diff --git a/pom.xml b/pom.xml index 6429e505..e6a480f3 100644 --- a/pom.xml +++ b/pom.xml @@ -35,8 +35,8 @@ 4.11 1.3 2.0.5-beta - 1.6.6 - 1.0.6 + 1.7.29 + 1.2.3 0.4.0 1.4 1.4 diff --git a/voms-admin-api/src/main/resources/rebel.xml b/voms-admin-api/src/main/resources/rebel.xml deleted file mode 100644 index d4e7148d..00000000 --- a/voms-admin-api/src/main/resources/rebel.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 815a0aeb..624a3351 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -44,6 +44,7 @@ 2.5.3 2.2.2 3.2 + 5.5.1 @@ -203,6 +204,20 @@ mockito-core test + + + org.mock-server + mockserver-netty + ${mock-server.version} + test + + + + org.mock-server + mockserver-client-java + ${mock-server.version} + test + org.hibernate diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java index e5bf694d..ec26840c 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java @@ -54,7 +54,7 @@ import eu.emi.security.authn.x509.impl.PEMCredential; -public final class VOMSConfiguration { +public class VOMSConfiguration { private static volatile VOMSConfiguration instance = null; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/AbstractPluginConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/AbstractPluginConfigurator.java index 133a4ab9..9355a5bf 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/AbstractPluginConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/AbstractPluginConfigurator.java @@ -21,6 +21,13 @@ public abstract class AbstractPluginConfigurator implements PluginConfigurator { private String pluginName = ""; + + private final VOMSConfiguration vomsConfig; + + public AbstractPluginConfigurator(VOMSConfiguration config) { + this.vomsConfig = config; + } + /** * @return the pluginName */ @@ -30,8 +37,7 @@ public String getPluginName() { } /** - * @param pluginName - * the pluginName to set + * @param pluginName the pluginName to set */ public void setPluginName(String pluginName) { @@ -40,20 +46,21 @@ public void setPluginName(String pluginName) { public String getPluginProperty(String propertyName, String defaultValue) { - return VOMSConfiguration.instance().getExternalValidatorProperty( - pluginName, propertyName, defaultValue); + return vomsConfig.getExternalValidatorProperty(pluginName, propertyName, defaultValue); } public String getPluginProperty(String propertyName) { - return VOMSConfiguration.instance().getExternalValidatorProperty( - pluginName, propertyName); + return vomsConfig.getExternalValidatorProperty(pluginName, propertyName); } public String getVomsConfigurationDirectoryPath() { - return VOMSConfiguration.instance().getConfigurationDirectoryPath(); + return vomsConfig.getConfigurationDirectoryPath(); } + public VOMSConfiguration getVomsConfig() { + return vomsConfig; + } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/PluginManager.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/PluginManager.java index f73fbb46..3598199b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/PluginManager.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/PluginManager.java @@ -80,12 +80,8 @@ public synchronized void configurePlugins() { Class confClazz = Class.forName(pluginConfClassName); - // I could have used a constructor method to pass down the pluginName - // to the actual plugin configurator, but the reflection constructor - // code - // is not somethin I really love... PluginConfigurator pluginConfigurator = (PluginConfigurator) confClazz - .newInstance(); + .getDeclaredConstructor(VOMSConfiguration.class).newInstance(conf); pluginConfigurator.setPluginName(pluginName); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DateUtils.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DateUtils.java new file mode 100644 index 00000000..0e9e059a --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DateUtils.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; + +public class DateUtils { + + private DateUtils() { + // empty on purpose + } + + public static final Date parseDate(String dateString) { + + LocalDate date = LocalDate.parse(dateString); + return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DefaultHrDbSyncTaskFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DefaultHrDbSyncTaskFactory.java new file mode 100644 index 00000000..a9148cfe --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/DefaultHrDbSyncTaskFactory.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.time.Clock; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.core.tasks.DatabaseTransactionTaskWrapper; +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; + +public class DefaultHrDbSyncTaskFactory implements HrDbSyncTaskFactory { + + private final Clock clock; + private final ValidationManager validationManager; + + public DefaultHrDbSyncTaskFactory() { + clock = Clock.systemDefaultZone(); + validationManager = ValidationManager.instance(); + } + + public DefaultHrDbSyncTaskFactory(Clock c, ValidationManager vm) { + clock = c; + validationManager = vm; + } + + @Override + public Runnable buildSyncTask(HrDbProperties properties, HrDbApiService api, VOMSUserDAO dao, + VOMSConfiguration config) { + + HrDefaultHandler handler = new HrDefaultHandler(clock, properties, validationManager); + HrDbSyncTask syncTask = new HrDbSyncTask(properties, api, dao, config); + + syncTask.setMissingRecordHandler(handler); + syncTask.setSyncHandler(handler); + + return new DatabaseTransactionTaskWrapper(syncTask, true, true, + properties.getMembesrshipCheck().getPeriodInSeconds()); + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiService.java new file mode 100644 index 00000000..c6780d32 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiService.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.util.Optional; + +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; + +public interface HrDbApiService { + + boolean hasValidExperimentParticipation(long cernPersonId); + + boolean hasValidExperimentParticipationByEmail(String email); + + Optional getVoPersonRecordByEmail(String email); + + Optional getVoPersonRecord(long cernPersonId); + + Optional lookupVomsUser(VOMSUser user); + + boolean hasValidExperimentParticipation(VOMSUser user); + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiServiceFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiServiceFactory.java new file mode 100644 index 00000000..f3783a29 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbApiServiceFactory.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +@FunctionalInterface +public interface HrDbApiServiceFactory { + + HrDbApiService newHrDbApiService(HrDbProperties properties); + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java new file mode 100644 index 00000000..96032a03 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java @@ -0,0 +1,212 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import static java.util.Objects.isNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.time.Clock; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.configuration.VOMSConfigurationConstants; +import org.glite.security.voms.admin.core.tasks.DatabaseTransactionTaskWrapper; +import org.glite.security.voms.admin.core.tasks.VOMSExecutorService; +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.integration.AbstractPluginConfigurator; +import org.glite.security.voms.admin.integration.VOMSPluginConfigurationException; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HrDbConfigurator extends AbstractPluginConfigurator { + + public static final Logger LOG = LoggerFactory.getLogger(HrDbConfigurator.class); + + public static final String DEFAULT_CONFIG_FILE_NAME = "orgdb.properties"; + + public static final String HR_DB_EXPERIMENT_NAME_PROPERTY = "experiment_name"; + public static final String HR_DB_MEMBERSHIP_CHECK_PERIOD_IN_SECONDS = "membership_check.period"; + + public static final String HR_DB_REGISTRATION_TYPE = "orgdb"; + + Clock clock; + VOMSExecutorService executorService; + VOMSUserDAO userDao; + ValidationManager validationManager; + HrDbApiServiceFactory apiServiceFactory; + HrDbSyncTaskFactory syncTaskFactory; + HrDbRequestValidatorFactory requestValidatorFactory; + HrDbProperties hrConfig; + + public HrDbConfigurator(VOMSConfiguration config) { + super(config); + } + + private HrDbProperties loadHrDBDatabaseProperties() throws VOMSPluginConfigurationException { + + String defaultConfigFilePath = + getVomsConfigurationDirectoryPath() + "/" + DEFAULT_CONFIG_FILE_NAME; + String configFilePath = getPluginProperty("configFile", defaultConfigFilePath); + + Properties hrDbProps = new Properties(); + + try { + hrDbProps.load(new FileInputStream(new File(configFilePath))); + + } catch (IOException e) { + + String errorMessage = String.format("Configuration file '%s' for plugin '%s' does not exist!", + configFilePath, getPluginName()); + throw new VOMSPluginConfigurationException(errorMessage, e); + + } + + return HrDbProperties.fromProperties(hrDbProps); + } + + Runnable wrapTask(Runnable task) { + return new DatabaseTransactionTaskWrapper(task, true, true); + } + + void initDependencies() throws VOMSPluginConfigurationException { + + if (isNull(clock)) { + clock = Clock.systemDefaultZone(); + } + + if (isNull(apiServiceFactory)) { + apiServiceFactory = new HttpClientHrDbApiServiceFactory(); + } + + if (isNull(executorService)) { + executorService = VOMSExecutorService.instance(); + } + + if (isNull(validationManager)) { + validationManager = ValidationManager.instance(); + } + + if (isNull(userDao)) { + userDao = VOMSUserDAO.instance(); + } + + if (isNull(hrConfig)) { + hrConfig = loadHrDBDatabaseProperties(); + } + } + + private void scheduleSyncTask(HrDbProperties config, Runnable syncTask) { + + final Runnable task = wrapTask(syncTask); + ZonedDateTime now = ZonedDateTime.now(clock); + ZonedDateTime nextRun = + now.withHour(config.getMembesrshipCheck().getStartHour()).withMinute(0).withSecond(0); + + if (now.compareTo(nextRun) > 0) { + nextRun = nextRun.plusDays(1); + } + + LOG.info("Scheduling HR DB sync task to start on {} and run every {} seconds", nextRun, + config.getMembesrshipCheck().getPeriodInSeconds()); + + Duration duration = Duration.between(now, nextRun); + + executorService.scheduleAtFixedRate(task, duration.getSeconds(), + config.getMembesrshipCheck().getPeriodInSeconds(), TimeUnit.SECONDS); + + if (config.getMembesrshipCheck().isRunAtStartup()) { + + ZonedDateTime startupRun = now.plusMinutes(5); + + if (Duration.between(startupRun, nextRun).compareTo(Duration.ofMinutes(30)) <= 0) { + LOG.info( + "Not scheduling the HR DB sync task startup run, as the periodic run is scheduled within 30 minutes"); + } else { + LOG.info( + "Scheduling a startup run of the HR DB sync task in 5 minutes as requested by configuration"); + executorService.schedule(task, 300, TimeUnit.SECONDS); + } + } + } + + @Override + public void configure() throws VOMSPluginConfigurationException { + LOG.debug("HR DB voms plugin configuration started"); + + initDependencies(); + + VOMSConfiguration config = getVomsConfig(); + config.setRegistrationType(HR_DB_REGISTRATION_TYPE); + config.setProperty(VOMSConfigurationConstants.VOMS_INTERNAL_RO_PERSONAL_INFORMATION, + Boolean.TRUE); + config.setProperty(VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, + Boolean.TRUE); + + HrDbApiService api = apiServiceFactory.newHrDbApiService(hrConfig); + + validationManager + .setRequestValidationContext(requestValidatorFactory.newHrDbRequestValidator(hrConfig, api)); + + LOG.info("HR DB request validator registered succesfully"); + + if (hrConfig.getMembesrshipCheck().isEnabled()) { + scheduleSyncTask(hrConfig, syncTaskFactory.buildSyncTask(hrConfig, api, userDao, config)); + } else { + LOG.info("HR DB sync task DISABLED as requested by configuration"); + } + + LOG.info("HR DB voms plugin started"); + + } + + public void setExecutorService(VOMSExecutorService executorService) { + this.executorService = executorService; + } + + public void setValidationManager(ValidationManager validationManager) { + this.validationManager = validationManager; + } + + public void setApiServiceFactory(HrDbApiServiceFactory apiServiceFactory) { + this.apiServiceFactory = apiServiceFactory; + } + + public void setUserDao(VOMSUserDAO userDao) { + this.userDao = userDao; + } + + public void setSyncTaskFactory(HrDbSyncTaskFactory syncTaskFactory) { + this.syncTaskFactory = syncTaskFactory; + } + + public void setRequestValidatorFactory(HrDbRequestValidatorFactory requestValidatorFactory) { + this.requestValidatorFactory = requestValidatorFactory; + } + + public void setClock(Clock clock) { + this.clock = clock; + } + + public void setHrConfig(HrDbProperties hrConfig) { + this.hrConfig = hrConfig; + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbError.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbError.java new file mode 100644 index 00000000..28515689 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbError.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +public class HrDbError extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public HrDbError(String message) { + super(message); + } + + public HrDbError(Throwable cause) { + super(cause); + } + + public HrDbError(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java new file mode 100644 index 00000000..f83c5bac --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java @@ -0,0 +1,208 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import static java.lang.String.format; + +import java.util.Properties; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +public class HrDbProperties { + + public static final String EXPERIMENT_KEY = "experiment"; + public static final String MEMBERSHIP_CHECK_PERIOD_KEY = "membership_check.period"; + public static final String MEMBERSHIP_CHECK_ENABLED_KEY = "membership_check.enabled"; + public static final String MEMBERSHIP_CHECK_START_HOUR_KEY = "membership_check.start_hour"; + public static final String MEMBERSHIP_CHECK_RUN_AT_STARTUP_KEY = + "membership_check.run_at_startup"; + + public static final String API_ENDPOINT_KEY = "api.endpoint"; + public static final String API_USERNAME_KEY = "api.username"; + public static final String API_PASSWORD_KEY = "api.password"; + public static final String API_TIMEOUT_KEY = "api.timeout_secs"; + + public static final String[] REQUIRED_KEYS = + {EXPERIMENT_KEY, API_ENDPOINT_KEY, API_USERNAME_KEY, API_PASSWORD_KEY}; + + public static class MembershipCheck { + + boolean enabled = true; + + boolean runAtStartup = true; + + int startHour = 23; + + long periodInSeconds = TimeUnit.HOURS.toSeconds(12); + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public long getPeriodInSeconds() { + return periodInSeconds; + } + + public void setPeriodInSeconds(long periodInSeconds) { + this.periodInSeconds = periodInSeconds; + } + + public int getStartHour() { + return startHour; + } + + public void setStartHour(int startHour) { + this.startHour = startHour; + } + + public void setRunAtStartup(boolean runAtStartup) { + this.runAtStartup = runAtStartup; + } + + public boolean isRunAtStartup() { + return runAtStartup; + } + } + + public static class HrDbApiProperties { + + String endpoint = "http://localhost:8080"; + String username = "user"; + String password = "pwd"; + + long timeoutInSeconds = 5L; + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setTimeoutInSeconds(long timeoutInSeconds) { + this.timeoutInSeconds = timeoutInSeconds; + } + + public long getTimeoutInSeconds() { + return timeoutInSeconds; + } + } + + HrDbApiProperties api = new HrDbApiProperties(); + MembershipCheck membesrshipCheck = new MembershipCheck(); + + String experimentName = "experiment"; + + public HrDbApiProperties getApi() { + return api; + } + + public void setApi(HrDbApiProperties api) { + this.api = api; + } + + public String getExperimentName() { + return experimentName; + } + + public void setExperimentName(String experimentName) { + this.experimentName = experimentName; + } + + public void setMembesrshipCheck(MembershipCheck membesrshipCheck) { + this.membesrshipCheck = membesrshipCheck; + } + + public MembershipCheck getMembesrshipCheck() { + return membesrshipCheck; + } + + private static void requireProperty(String key, Properties properties) { + if (!properties.containsKey(key)) { + throw new HrDbError(format("Configuration error: required property '%s' not found", key)); + } + } + + public static final HrDbProperties fromProperties(Properties properties) { + + Stream.of(REQUIRED_KEYS).forEach(p -> requireProperty(p, properties)); + + HrDbProperties config = new HrDbProperties(); + + config.setExperimentName(properties.getProperty(EXPERIMENT_KEY)); + + if (properties.containsKey(MEMBERSHIP_CHECK_START_HOUR_KEY)) { + int startHour = Integer.parseInt(properties.getProperty(MEMBERSHIP_CHECK_START_HOUR_KEY)); + + if (startHour >= 0 && startHour < 24) { + config.getMembesrshipCheck() + .setStartHour( + (Integer.parseInt(properties.getProperty(MEMBERSHIP_CHECK_START_HOUR_KEY)))); + } + } + + if (properties.containsKey(MEMBERSHIP_CHECK_RUN_AT_STARTUP_KEY)) { + config.getMembesrshipCheck() + .setRunAtStartup( + Boolean.parseBoolean(properties.getProperty(MEMBERSHIP_CHECK_RUN_AT_STARTUP_KEY))); + } + + if (properties.containsKey(MEMBERSHIP_CHECK_PERIOD_KEY)) { + config.getMembesrshipCheck() + .setPeriodInSeconds(Long.parseLong(properties.getProperty(MEMBERSHIP_CHECK_PERIOD_KEY))); + } + + if (properties.containsKey(MEMBERSHIP_CHECK_ENABLED_KEY)) { + config.getMembesrshipCheck().setEnabled(Boolean.parseBoolean(MEMBERSHIP_CHECK_ENABLED_KEY)); + } + + config.getApi().setEndpoint(properties.getProperty(API_ENDPOINT_KEY)); + config.getApi().setUsername(properties.getProperty(API_USERNAME_KEY)); + config.getApi().setPassword(properties.getProperty(API_PASSWORD_KEY)); + + if (properties.containsKey(API_TIMEOUT_KEY)) { + long apiTimeout = Long.parseLong(properties.getProperty(API_TIMEOUT_KEY)); + + if (apiTimeout > 0) { + config.getApi().setTimeoutInSeconds(apiTimeout); + } + } + + return config; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java new file mode 100644 index 00000000..abdbf063 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import static org.glite.security.voms.admin.core.validation.RequestValidationResult.success; + +import java.time.Clock; +import java.util.List; +import java.util.Optional; + +import org.glite.security.voms.admin.core.validation.RequestValidationContext; +import org.glite.security.voms.admin.core.validation.RequestValidationResult; +import org.glite.security.voms.admin.core.validation.strategies.RequestValidationStrategy; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.request.NewVOMembershipRequest; + +import com.google.common.collect.Lists; + +public class HrDbRequestValidator + implements RequestValidationStrategy, RequestValidationContext { + + final Clock clock; + final HrDbProperties properties; + final HrDbApiService apiService; + + public HrDbRequestValidator(Clock clock, HrDbProperties properties, HrDbApiService apiService) { + this.clock = clock; + this.properties = properties; + this.apiService = apiService; + } + + @Override + public RequestValidationStrategy getVOMembershipRequestValidationStrategy() { + return this; + } + + RequestValidationResult dataMismatch(String email, List errors) { + RequestValidationResult result = RequestValidationResult + .failure("HR DB validation failed. The HR DB VOMS person record linked to email address '" + + email + "' did not match the data you entered."); + result.setErrorMessages(errors); + + return result; + } + + + RequestValidationResult noParticipationFound(String email) { + return RequestValidationResult.failure("No HR db participation found matching email '" + email + + "' for experiment '" + properties.getExperimentName() + "'."); + } + + protected void propertyEqualsIgnoreCase(String value1, String value2, String propertyName, + List errors) { + + if (!value1.equalsIgnoreCase(value2)) { + + String errorMessage = String.format("Property '" + propertyName + + "' does not match (ignoring case) the OrgDB VOMS person record. You entered '%s', while '%s' was expected.", + value1, value2); + errors.add(errorMessage); + } + + } + + RequestValidationResult validateRequestData(NewVOMembershipRequest request, VOPersonDTO person) { + Optional participation = person + .findValidParticipationsForExperiment(clock.instant(), properties.getExperimentName()); + + if (participation.isPresent()) { + + List validationErrors = Lists.newArrayList(); + + propertyEqualsIgnoreCase(request.getRequesterInfo().getName(), person.getFirstName(), "name", + validationErrors); + propertyEqualsIgnoreCase(request.getRequesterInfo().getSurname(), person.getName(), "surname", + validationErrors); + + + if (!validationErrors.isEmpty()) { + return dataMismatch(request.getRequesterInfo().getEmailAddress(), validationErrors); + } + + return success(); + + } else { + return noParticipationFound(request.getRequesterInfo().getEmailAddress()); + } + } + + @Override + public RequestValidationResult validateRequest(NewVOMembershipRequest r) { + + String requestorEmail = r.getRequesterInfo().getEmailAddress(); + + Optional voPerson = apiService.getVoPersonRecordByEmail(requestorEmail); + + if (voPerson.isPresent()) { + + return validateRequestData(r, voPerson.get()); + + } else { + return noParticipationFound(requestorEmail); + } + + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidatorFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidatorFactory.java new file mode 100644 index 00000000..91434ca5 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidatorFactory.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +public interface HrDbRequestValidatorFactory { + HrDbRequestValidator newHrDbRequestValidator(HrDbProperties properties, HrDbApiService api); +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java new file mode 100644 index 00000000..41a991b6 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.util.Optional; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.integration.cern.strategies.MembershipSynchronizationStrategy; +import org.glite.security.voms.admin.integration.cern.strategies.MissingMembershipRecordStrategy; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.hibernate.ScrollableResults; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HrDbSyncTask implements Runnable { + + public static final Logger LOG = LoggerFactory.getLogger(HrDbSyncTask.class); + + final HrDbProperties hrConfig; + final HrDbApiService hrDbApi; + final VOMSConfiguration vomsConfig; + final VOMSUserDAO dao; + + private MembershipSynchronizationStrategy syncHandler = (u, p) -> { + }; + + private MissingMembershipRecordStrategy missingRecordHandler = u -> { + }; + + public HrDbSyncTask(HrDbProperties properties, HrDbApiService api, VOMSUserDAO dao, + VOMSConfiguration vomsConfiguration) { + this.hrConfig = properties; + this.vomsConfig = vomsConfiguration; + this.dao = dao; + this.hrDbApi = api; + } + + + @Override + public void run() { + ScrollableResults userCursor = dao.findAllWithCursor(); + + while (userCursor.next()) { + VOMSUser user = (VOMSUser) userCursor.get(0); + + try { + + Optional voPerson = hrDbApi.lookupVomsUser(user); + + if (voPerson.isPresent()) { + syncHandler.synchronizeMembershipInformation(user, voPerson.get()); + } else { + missingRecordHandler.handleMissingHrRecord(user); + } + + } catch (HrDbError apiError) { + LOG.error("Error querying HR Db API for user {}: {}", user.getShortName(), + apiError.getMessage()); + + if (LOG.isDebugEnabled()) { + LOG.error(apiError.getMessage(), apiError); + } + } + } + + } + + public void setMissingRecordHandler(MissingMembershipRecordStrategy missingRecordHandler) { + this.missingRecordHandler = missingRecordHandler; + } + + public void setSyncHandler(MembershipSynchronizationStrategy syncHandler) { + this.syncHandler = syncHandler; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTaskFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTaskFactory.java new file mode 100644 index 00000000..2166d2a7 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTaskFactory.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; + +public interface HrDbSyncTaskFactory { + Runnable buildSyncTask(HrDbProperties properties, HrDbApiService api, VOMSUserDAO dao, + VOMSConfiguration config); +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java new file mode 100644 index 00000000..64788e02 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.time.Clock; +import java.time.Instant; +import java.util.Date; +import java.util.Optional; + +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.integration.cern.strategies.ExpiredParticipationStrategy; +import org.glite.security.voms.admin.integration.cern.strategies.MembershipSynchronizationStrategy; +import org.glite.security.voms.admin.integration.cern.strategies.MissingMembershipRecordStrategy; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.glite.security.voms.admin.persistence.model.VOMSUser.SuspensionReason; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HrDefaultHandler implements ExpiredParticipationStrategy, + MembershipSynchronizationStrategy, MissingMembershipRecordStrategy { + + public static final Logger LOG = LoggerFactory.getLogger(HrDefaultHandler.class); + + private final Clock clock; + private final ValidationManager manager; + private final HrDbProperties config; + + public HrDefaultHandler(Clock clock, HrDbProperties hrConfig, + ValidationManager validationManager) { + this.clock = clock; + this.manager = validationManager; + this.config = hrConfig; + } + + @Override + public void handleMissingHrRecord(VOMSUser user) { + LOG.info("No HR record found for user: {}", user.getShortName()); + + SuspensionReason reason = SuspensionReason.HR_DB_VALIDATION; + reason.setMessage("OrgDB: No record found"); + + manager.suspendUser(user, reason); + } + + protected void restoreUserIfNeeded(VOMSUser u) { + if (u.isSuspended()) { + + if (u.getSuspensionReasonCode() == SuspensionReason.MEMBERSHIP_EXPIRATION + || u.getSuspensionReason().startsWith("OrgDB: ")) { + manager.restoreUser(u); + } + } + + } + + + @Override + public void synchronizeMembershipInformation(VOMSUser user, VOPersonDTO voPerson) { + + LOG.info("Syncing user {} against record {}", user.getShortName(), voPerson.getId()); + Instant now = clock.instant(); + + user.setOrgDbId(voPerson.getId()); + + user.setName(voPerson.getFirstName()); + user.setSurname(voPerson.getName()); + + String orgDbEmailAddress = + Optional.ofNullable(voPerson.getPhysicalEmail()).orElse(voPerson.getEmail()); + + user.setEmailAddress(orgDbEmailAddress.toLowerCase()); + + Optional participation = + voPerson.findValidParticipationsForExperiment(now, config.getExperimentName()); + + if (participation.isPresent()) { + user.setEndTime(participation.get().getEndDate()); + restoreUserIfNeeded(user); + } else { + handleExpiredParticipation(user, voPerson); + } + } + + @Override + public void handleExpiredParticipation(VOMSUser u, VOPersonDTO voPerson) { + Instant now = clock.instant(); + + u.setEndTime(Date.from(now)); + + LOG.info( + "User {} HR experiment participation is no longer valid, setting VOMS membership end date to current time, i.e.: {}", + u.getShortName(), now); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java new file mode 100644 index 00000000..7a68e027 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import static java.util.Objects.isNull; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.time.Clock; +import java.time.Instant; +import java.util.Base64; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.client.ContentExchange; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpExchange; +import org.eclipse.jetty.util.ajax.JSON; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpClientHrDbApiService implements HrDbApiService { + + private static final Logger LOG = LoggerFactory.getLogger(HttpClientHrDbApiService.class); + + private final HttpClient client; + + final String experimentName; + final String voPersonRecordEndpoint; + final String voPersonRecordByEmailEndpoint; + final String validParticipationEndpoint; + final String basicAuthHeaderContent; + final Clock clock; + + public HttpClientHrDbApiService(Clock clock, HrDbProperties properties) { + client = new HttpClient(); + experimentName = properties.getExperimentName(); + this.clock = clock; + + basicAuthHeaderContent = Base64.getEncoder() + .encodeToString(String + .format("%s:%s", properties.getApi().getUsername(), properties.getApi().getPassword()) + .getBytes()); + + + voPersonRecordEndpoint = String.format("%s/api/VOPersons", properties.getApi().getEndpoint()); + voPersonRecordByEmailEndpoint = + String.format("%s/api/VOPersons/email", properties.getApi().getEndpoint()); + + validParticipationEndpoint = String.format("%s/api/VOPersons/participation/%s/valid", + properties.getApi().getEndpoint(), properties.getExperimentName()); + + + try { + client.setMaxRetries(3); + client.setTimeout(TimeUnit.SECONDS.toMillis(properties.getApi().getTimeoutInSeconds())); + client.start(); + } catch (Exception e) { + throw new HrDbError("Error initializing HTTP client", e); + } + } + + private String voPersonByEmailUrl(String email) { + return String.format("%s/%s", voPersonRecordByEmailEndpoint, email); + } + + private String voPersonRecordUrl(long cernPersonId) { + return String.format("%s/%d", voPersonRecordEndpoint, cernPersonId); + } + + private String validParticipationUrl(long cernPersonId) { + return String.format("%s/%d", validParticipationEndpoint, cernPersonId); + } + + private ContentExchange prepareHttpExchange(String url) { + ContentExchange ce = new ContentExchange(); + ce.setRetryStatus(true); + ce.setRequestHeader("Authorization", String.format("Basic %s", basicAuthHeaderContent)); + ce.setRequestHeader("Accept", "application/json"); + + ce.setURL(url); + + return ce; + } + + protected void handleExchange(ContentExchange ce) { + try { + + client.send(ce); + int exchangeStatus = ce.waitForDone(); + + if (HttpExchange.STATUS_COMPLETED == exchangeStatus) { + if (ce.getResponseStatus() != 200) { + + final String errorMsg = + String.format("HR Db Api Http request %s yelded response status: %d ", + ce.getRequestURI(), ce.getResponseStatus()); + throw new HrDbError(errorMsg); + } + } else if (HttpExchange.STATUS_EXPIRED == exchangeStatus){ + throw new HrDbError("Error contacting the HR DB api: request timeout exceeded"); + } else { + throw new HrDbError("Error contacting the HR DB api"); + } + + } catch (IOException e) { + throw new HrDbError("Error contacting the HR DB api: " + e.getMessage(), e); + } catch (InterruptedException e) { + LOG.warn(e.getMessage(), e); + } + } + + protected Optional voPersonExchange(ContentExchange ce) { + handleExchange(ce); + + try { + + @SuppressWarnings("unchecked") + Map jsonMap = (Map) JSON.parse(ce.getResponseContent()); + + return Optional.of(VOPersonDTO.fromJsonMap(jsonMap)); + + } catch (UnsupportedEncodingException e) { + throw new HrDbError(e.getMessage(), e); + } + } + + @Override + public Optional getVoPersonRecord(long cernPersonId) { + return voPersonExchange(prepareHttpExchange(voPersonRecordUrl(cernPersonId))); + } + + @Override + public boolean hasValidExperimentParticipation(long cernPersonId) { + + ContentExchange ce = prepareHttpExchange(validParticipationUrl(cernPersonId)); + + handleExchange(ce); + + try { + return Boolean.parseBoolean(ce.getResponseContent()); + } catch (UnsupportedEncodingException e) { + throw new HrDbError(e.getMessage(), e); + } + + + } + + @Override + public Optional lookupVomsUser(VOMSUser user) { + + Long orgDbId = user.getOrgDbId(); + + if (!isNull(orgDbId)) { + return getVoPersonRecord(orgDbId); + } + return Optional.empty(); + } + + @Override + public boolean hasValidExperimentParticipation(VOMSUser user) { + return lookupVomsUser(user).map(p -> hasValidExperimentParticipation(p.getId())).orElse(false); + } + + @Override + public Optional getVoPersonRecordByEmail(String email) { + return voPersonExchange(prepareHttpExchange(voPersonByEmailUrl(email))); + } + + @Override + public boolean hasValidExperimentParticipationByEmail(String email) { + + Instant now = clock.instant(); + + return getVoPersonRecordByEmail(email) + .map(p -> p.findValidParticipationsForExperiment(now, experimentName)) + .isPresent(); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiServiceFactory.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiServiceFactory.java new file mode 100644 index 00000000..4643dacc --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiServiceFactory.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern; + +import java.time.Clock; + +public class HttpClientHrDbApiServiceFactory implements HrDbApiServiceFactory { + + @Override + public HrDbApiService newHrDbApiService(HrDbProperties properties) { + + return new HttpClientHrDbApiService(Clock.systemDefaultZone(), properties); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java new file mode 100644 index 00000000..b72c9be3 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.dto; + +public class ErrorDTO { + + final String error; + final String errorMessage; + + private ErrorDTO(String error, String errorMessage) { + this.error = error; + this.errorMessage = errorMessage; + } + + private ErrorDTO(String error) { + this(error, null); + } + + public String getError() { + return error; + } + + public String getErrorMessage() { + return errorMessage; + } + + public static ErrorDTO newError(String error, String errorMessage) { + return new ErrorDTO(error, errorMessage); + } + + public static ErrorDTO newError(String error) { + return new ErrorDTO(error); + } + + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/InstituteDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/InstituteDTO.java new file mode 100644 index 00000000..677ebe9b --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/InstituteDTO.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.dto; + +import java.util.Map; + +public class InstituteDTO { + + String id; + + String name; + + String town; + + String country; + + public InstituteDTO() { + // empty ctor + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTown() { + return town; + } + + public void setTown(String town) { + this.town = town; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public String toString() { + return "InstituteDTO [id=" + id + ", name=" + name + ", town=" + town + ", country=" + country + + "]"; + } + + public static InstituteDTO fromJson(Map map) { + + InstituteDTO institute = new InstituteDTO(); + institute.setId((String)map.get("id")); + institute.setCountry((String)map.get("country")); + institute.setName((String)map.get("name")); + institute.setTown((String)map.get("town")); + return institute; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ListResponseDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ListResponseDTO.java new file mode 100644 index 00000000..0db91a47 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ListResponseDTO.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.dto; + +import java.util.List; + +public class ListResponseDTO { + + private final long totalResults; + private final int itemsPerPage; + private final int startIndex; + + private final List resources; + + private ListResponseDTO(Builder builder) { + this.totalResults = builder.totalResults; + this.startIndex = builder.startIndex; + this.itemsPerPage = builder.itemsPerPage; + this.resources = builder.resources; + } + + public long getTotalResults() { + return totalResults; + } + + public int getItemsPerPage() { + return itemsPerPage; + } + + public int getStartIndex() { + return startIndex; + } + + public List getResources() { + return resources; + } + + public static class Builder { + private long totalResults; + private int itemsPerPage; + private int startIndex; + private List resources; + + public Builder totalResults(long totalResults) { + this.totalResults = totalResults; + return this; + } + + public Builder itemsPerPage(int itemsPerPage) { + this.itemsPerPage = itemsPerPage; + return this; + } + + public Builder startIndex(int startIndex) { + this.startIndex = startIndex; + return this; + } + + public Builder resources(List resources) { + this.resources = resources; + return this; + } + + public ListResponseDTO build() { + return new ListResponseDTO<>(this); + } + } + + public static Builder builder() { + return new Builder<>(); + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ParticipationDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ParticipationDTO.java new file mode 100644 index 00000000..dc5f22bb --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ParticipationDTO.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.dto; + +import static java.util.Objects.isNull; + +import java.time.Instant; +import java.util.Date; +import java.util.Map; +import java.util.Objects; + +import org.glite.security.voms.admin.integration.cern.DateUtils; + + +public class ParticipationDTO { + + InstituteDTO institute; + String experiment; + + Date startDate; + Date endDate; + + public ParticipationDTO() { + // empty ctor + } + + public InstituteDTO getInstitute() { + return institute; + } + + public void setInstitute(InstituteDTO institute) { + this.institute = institute; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public String getExperiment() { + return experiment; + } + + public void setExperiment(String experiment) { + this.experiment = experiment; + } + + public boolean isValidAtInstant(Instant instant) { + + Date now = Date.from(instant); + + return getStartDate().before(Date.from(instant)) + && (isNull(getEndDate()) || getEndDate().after(now)); + } + + @Override + public String toString() { + return "ParticipationDTO [institute=" + institute + ", experiment=" + experiment + + ", startDate=" + startDate + ", endDate=" + endDate + "]"; + } + + + @SuppressWarnings("unchecked") + public static ParticipationDTO fromJsonMap(Map json) { + ParticipationDTO participation = new ParticipationDTO(); + participation.setExperiment((String) json.get("experiment")); + participation.setStartDate(DateUtils.parseDate((String) json.get("startDate"))); + String endDate = (String) json.get("endDate"); + if (!Objects.isNull(endDate)) { + participation.setEndDate(DateUtils.parseDate(endDate)); + } + + participation.setInstitute(InstituteDTO.fromJson((Map) json.get("institute"))); + return participation; + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java new file mode 100644 index 00000000..9bf01cbf --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.dto; + + +import java.time.Instant; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + + +public class VOPersonDTO { + + private Long id; + private String name; + private String firstName; + private String department; + private String group; + private String sector; + private String building; + private String floor; + private String room; + private String tel1; + private String tel2; + private String tel3; + private String portablePhone; + private String beeper; + private String email; + private String physicalEmail; + private Set participations; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getSector() { + return sector; + } + + public void setSector(String sector) { + this.sector = sector; + } + + public String getBuilding() { + return building; + } + + public void setBuilding(String building) { + this.building = building; + } + + public String getFloor() { + return floor; + } + + public void setFloor(String floor) { + this.floor = floor; + } + + public String getRoom() { + return room; + } + + public void setRoom(String room) { + this.room = room; + } + + public String getTel1() { + return tel1; + } + + public void setTel1(String tel1) { + this.tel1 = tel1; + } + + public String getTel2() { + return tel2; + } + + public void setTel2(String tel2) { + this.tel2 = tel2; + } + + public String getTel3() { + return tel3; + } + + public void setTel3(String tel3) { + this.tel3 = tel3; + } + + public String getPortablePhone() { + return portablePhone; + } + + public void setPortablePhone(String portablePhone) { + this.portablePhone = portablePhone; + } + + public String getBeeper() { + return beeper; + } + + public void setBeeper(String beeper) { + this.beeper = beeper; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhysicalEmail() { + return physicalEmail; + } + + public void setPhysicalEmail(String physicalEmail) { + this.physicalEmail = physicalEmail; + } + + public Set getParticipations() { + return participations; + } + + public void setParticipations(Set participations) { + this.participations = participations; + } + + public Optional findValidParticipationsForExperiment(Instant now, + String experimentName) { + + return getParticipations().stream() + .filter(p -> p.getExperiment().equals(experimentName) && p.isValidAtInstant(now)) + .findFirst(); + } + + @Override + public String toString() { + return "VOPersonDTO [id=" + id + ", name=" + name + ", firstName=" + firstName + ", department=" + + department + ", group=" + group + ", sector=" + sector + ", building=" + building + + ", floor=" + floor + ", room=" + room + ", tel1=" + tel1 + ", tel2=" + tel2 + ", tel3=" + + tel3 + ", portablePhone=" + portablePhone + ", beeper=" + beeper + ", email=" + email + + ", physicalEmail=" + physicalEmail + ", participations=" + participations + "]"; + } + + @SuppressWarnings("unchecked") + public static VOPersonDTO fromJsonMap(Map json) { + VOPersonDTO person = new VOPersonDTO(); + person.setId((Long) json.get("id")); + person.setName((String) json.get("name")); + person.setFirstName((String) json.get("firstName")); + person.setEmail((String) json.get("email")); + person.setPhysicalEmail((String) json.get("physicalEmail")); + + + Object[] participations = (Object[]) json.get("participations"); + + person.setParticipations(Stream.of(participations) + .map(m -> ParticipationDTO.fromJsonMap((Map) m)) + .collect(Collectors.toSet())); + return person; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/ExpiredParticipationStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/ExpiredParticipationStrategy.java new file mode 100644 index 00000000..c4e6ca33 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/ExpiredParticipationStrategy.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.strategies; + +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; + +@FunctionalInterface +public interface ExpiredParticipationStrategy { + public void handleExpiredParticipation(VOMSUser u, VOPersonDTO voPerson); +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MembershipSynchronizationStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MembershipSynchronizationStrategy.java new file mode 100644 index 00000000..d9c12ab9 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MembershipSynchronizationStrategy.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.strategies; + +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; + +@FunctionalInterface +public interface MembershipSynchronizationStrategy { + + public void synchronizeMembershipInformation(VOMSUser user, VOPersonDTO voPerson); + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MissingMembershipRecordStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MissingMembershipRecordStrategy.java new file mode 100644 index 00000000..ff1db3f0 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/strategies/MissingMembershipRecordStrategy.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.integration.cern.strategies; + +import org.glite.security.voms.admin.persistence.model.VOMSUser; + +public interface MissingMembershipRecordStrategy { + public void handleMissingHrRecord(VOMSUser user); +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java index 39e85fa6..2e5438fc 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java @@ -38,6 +38,10 @@ public class OrgDBConfigurator extends AbstractPluginConfigurator { + public OrgDBConfigurator(VOMSConfiguration config) { + super(config); + } + public static final Logger log = LoggerFactory .getLogger(OrgDBConfigurator.class); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java index 3995b0f2..3a442a2b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java @@ -89,9 +89,9 @@ public enum SuspensionReason { FAILED_TO_SIGN_AUP("User failed to sign the AUP in time."), MEMBERSHIP_EXPIRATION("User membership has expired."), - SECURITY_INCIDENT( - "User membership has been suspended after a security incident."), - OTHER("User membership has been suspended for another unknown reason."); + SECURITY_INCIDENT("User membership has been suspended after a security incident."), + OTHER("User membership has been suspended for another unknown reason."), + HR_DB_VALIDATION("OrgDB: CERN HR db validation failed"); String message; @@ -118,7 +118,7 @@ public VOMSUser() { @Id @Column(name = "userid") - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; // Base membership information (JSPG requirements) @@ -163,32 +163,27 @@ public VOMSUser() { String suspensionReason; /** Generic attributes mapping **/ - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "user", orphanRemoval=true) + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) Set attributes = new HashSet(); /** Membership mappings **/ - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "user", orphanRemoval=true) + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) @SortNatural Set mappings = new TreeSet(); /** User certificates **/ - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "user", - fetch=FetchType.EAGER) - @org.hibernate.annotations.Cascade( - value = { org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", fetch = FetchType.EAGER) + @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) Set certificates = new HashSet(); /** AUP acceptance records **/ - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "user") - @org.hibernate.annotations.Cascade( - value = { org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user") + @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) Set aupAcceptanceRecords = new HashSet(); /** Assigned tasks **/ - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "user", - fetch = FetchType.EAGER) - @org.hibernate.annotations.Cascade( - value = { org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", fetch = FetchType.EAGER) + @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) Set tasks = new HashSet(); /** Personal information set **/ @@ -252,8 +247,7 @@ public VOMSUserAttribute getAttributeByName(String name) { while (i.hasNext()) { VOMSUserAttribute tmp = (VOMSUserAttribute) i.next(); - if (tmp.getName() - .equals(name)) + if (tmp.getName().equals(name)) return tmp; } @@ -271,7 +265,7 @@ public void deleteAttribute(VOMSUserAttribute val) { if (!attributes.contains(val)) throw new NoSuchAttributeException( - "Attribute \"" + val.getName() + "\" undefined for user " + this); + "Attribute \"" + val.getName() + "\" undefined for user " + this); attributes.remove(val); @@ -283,30 +277,30 @@ public void setAttribute(String name, String value) { if (val == null) throw new NoSuchAttributeException( - "Attribute \"" + name + "\" undefined for user \"" + this + "\"."); + "Attribute \"" + name + "\" undefined for user \"" + this + "\"."); val.setValue(value); } - - public void cleanMappings(){ - + + public void cleanMappings() { + Iterator mappingsIter = getMappings().iterator(); - - while (mappingsIter.hasNext()){ + + while (mappingsIter.hasNext()) { VOMSMapping m = mappingsIter.next(); mappingsIter.remove(); - + m.getGroup().removeMapping(m); - + isTrue(!m.getGroup().getMappings().contains(m)); - - if (m.getRole()!= null){ + + if (m.getRole() != null) { m.getRole().removeMapping(m); - + isTrue(!m.getRole().getMappings().contains(m)); } - + HibernateFactory.getSession().delete(m); } } @@ -326,21 +320,19 @@ public boolean isMember(String groupName) { if (groupName == null) throw new NullArgumentException( - "Cannot org.glite.security.voms.admin.test membership in a null group!"); + "Cannot org.glite.security.voms.admin.test membership in a null group!"); if (!PathNamingScheme.isGroup(groupName)) throw new VOMSSyntaxException( - "Group name passed as argument does not respect the VOMS FQAN syntax. [" - + groupName + "]"); + "Group name passed as argument does not respect the VOMS FQAN syntax. [" + groupName + + "]"); Iterator i = getMappings().iterator(); while (i.hasNext()) { VOMSMapping m = (VOMSMapping) i.next(); - if (m.getGroup() - .getName() - .equals(groupName) && m.isGroupMapping()) + if (m.getGroup().getName().equals(groupName) && m.isGroupMapping()) return true; } @@ -352,15 +344,14 @@ public boolean isMember(VOMSGroup g) { if (g == null) throw new NullArgumentException( - "Cannot org.glite.security.voms.admin.test membership in a null group!"); + "Cannot org.glite.security.voms.admin.test membership in a null group!"); Iterator i = getMappings().iterator(); while (i.hasNext()) { VOMSMapping m = (VOMSMapping) i.next(); - if (m.getGroup() - .equals(g) && m.isGroupMapping()) + if (m.getGroup().equals(g) && m.isGroupMapping()) return true; } @@ -373,16 +364,16 @@ public void addToGroup(VOMSGroup g) { log.debug("Adding user \"" + this + "\" to group \"" + g + "\"."); VOMSMapping m = new VOMSMapping(this, g, null); - + if (!getMappings().add(m)) throw new AlreadyExistsException( - "User \"" + this + "\" is already a member of group \"" + g + "\"."); - + "User \"" + this + "\" is already a member of group \"" + g + "\"."); + m.getGroup().addMapping(m); - + // Add this user to parent groups if (!g.isRootGroup()) { - if (!isMember(g.parent)){ + if (!isMember(g.parent)) { addToGroup(g.parent); } } @@ -403,7 +394,7 @@ public void removeFromGroup(VOMSGroup g) { } else throw new NoSuchMappingException( - "User \"" + this + "\" is not a member of group \"" + g + "\"."); + "User \"" + this + "\" is not a member of group \"" + g + "\"."); } @@ -411,19 +402,17 @@ public VOMSMapping assignRole(VOMSGroup g, VOMSRole r) { if (!isMember(g)) throw new NoSuchMappingException( - "User \"" + this + "\" is not a member of group \"" + g + "\"."); + "User \"" + this + "\" is not a member of group \"" + g + "\"."); VOMSMapping m = new VOMSMapping(this, g, r); if (getMappings().contains(m)) - throw new AlreadyExistsException("User \"" + this - + "\" already has role \"" + r + "\" in group \"" + g + "\"."); + throw new AlreadyExistsException( + "User \"" + this + "\" already has role \"" + r + "\" in group \"" + g + "\"."); - log.debug("Assigning role \"" + r + "\" to user \"" + this - + "\" in group \"" + g + "\"."); + log.debug("Assigning role \"" + r + "\" to user \"" + this + "\" in group \"" + g + "\"."); getMappings().add(m); - r.getMappings() - .add(m); + r.getMappings().add(m); return m; @@ -433,14 +422,13 @@ public VOMSMapping dismissRole(VOMSGroup g, VOMSRole r) { if (!isMember(g)) throw new NoSuchMappingException( - "User \"" + this + "\" is not a member of group \"" + g + "\"."); + "User \"" + this + "\" is not a member of group \"" + g + "\"."); if (!hasRole(g, r)) - throw new NoSuchMappingException("User \"" + this - + "\" does not have role \"" + r + "\" in group \"" + g + "\"."); + throw new NoSuchMappingException( + "User \"" + this + "\" does not have role \"" + r + "\" in group \"" + g + "\"."); - log.debug("Dismissing role \"" + r + "\" from user \"" + this - + "\" in group \"" + g + "\"."); + log.debug("Dismissing role \"" + r + "\" from user \"" + this + "\" in group \"" + g + "\"."); Iterator i = getMappings().iterator(); boolean removed = false; @@ -449,10 +437,7 @@ public VOMSMapping dismissRole(VOMSGroup g, VOMSRole r) { while (i.hasNext()) { m = (VOMSMapping) i.next(); if (m.isRoleMapping()) { - if (m.getGroup() - .equals(g) - && m.getRole() - .equals(r)) { + if (m.getGroup().equals(g) && m.getRole().equals(r)) { i.remove(); boolean removedFromRole = r.removeMapping(m); boolean removedFromGroup = g.removeMapping(m); @@ -462,8 +447,7 @@ public VOMSMapping dismissRole(VOMSGroup g, VOMSRole r) { } if (!removed) - throw new VOMSInconsistentDatabaseException( - "Error removing existing role mapping!"); + throw new VOMSInconsistentDatabaseException("Error removing existing role mapping!"); return m; } @@ -472,7 +456,7 @@ public void dismissRolesInGroup(VOMSGroup g) { if (!isMember(g)) throw new NoSuchMappingException( - "User \"" + this + "\" is not a member of group \"" + g + "\"."); + "User \"" + this + "\" is not a member of group \"" + g + "\"."); Iterator i = getMappings().iterator(); @@ -480,8 +464,7 @@ public void dismissRolesInGroup(VOMSGroup g) { VOMSMapping m = (VOMSMapping) i.next(); - if (m.getGroup() - .equals(g) && m.isRoleMapping()) { + if (m.getGroup().equals(g) && m.isRoleMapping()) { i.remove(); m.getRole().removeMapping(m); m.getGroup().removeMapping(m); @@ -495,7 +478,7 @@ public boolean hasRole(VOMSGroup g, VOMSRole r) { if (!isMember(g)) throw new NoSuchMappingException( - "User \"" + this + "\" is not a member of group \"" + g + "\"."); + "User \"" + this + "\" is not a member of group \"" + g + "\"."); Iterator i = getMappings().iterator(); @@ -503,10 +486,7 @@ public boolean hasRole(VOMSGroup g, VOMSRole r) { VOMSMapping m = (VOMSMapping) i.next(); if (m.isRoleMapping()) { - if (m.getGroup() - .equals(g) - && m.getRole() - .equals(r)) + if (m.getGroup().equals(g) && m.getRole().equals(r)) return true; } } @@ -518,7 +498,7 @@ public boolean hasRole(String fqan) { if (!PathNamingScheme.isQualifiedRole(fqan)) throw new IllegalArgumentException( - "Role name passed as argument is not a qualified role! [" + fqan + "]"); + "Role name passed as argument is not a qualified role! [" + fqan + "]"); String groupName = PathNamingScheme.getGroupName(fqan); String roleName = PathNamingScheme.getRoleName(fqan); @@ -529,12 +509,7 @@ public boolean hasRole(String fqan) { VOMSMapping m = (VOMSMapping) i.next(); if (m.isRoleMapping()) { - if (m.getGroup() - .getName() - .equals(groupName) - && m.getRole() - .getName() - .equals(roleName)) + if (m.getGroup().getName().equals(groupName) && m.getRole().getName().equals(roleName)) return true; } } @@ -566,8 +541,7 @@ public Set getRoles(VOMSGroup g) { while (mIter.hasNext()) { VOMSMapping m = (VOMSMapping) mIter.next(); - if (m.isRoleMapping() && m.getGroup() - .equals(g)) + if (m.isRoleMapping() && m.getGroup().equals(g)) res.add(m.getRole()); } @@ -648,8 +622,7 @@ public User asUser() { User u = new User(); u.setDN(getDefaultCertificate().getSubjectString()); - u.setCA(getDefaultCertificate().getCa() - .getSubjectString()); + u.setCA(getDefaultCertificate().getCa().getSubjectString()); u.setCN(null); u.setMail(getEmailAddress()); u.setCertUri(null); @@ -668,8 +641,7 @@ public static User[] collectionAsUsers(Collection c) { for (Certificate cert : u.getCertificates()) { User uu = new User(); uu.setDN(cert.getSubjectString()); - uu.setCA(cert.getCa() - .getSubjectString()); + uu.setCA(cert.getCa().getSubjectString()); uu.setMail(u.getEmailAddress()); userList.add(uu); } @@ -699,8 +671,8 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((getDefaultCertificate() == null) ? 0 : - getDefaultCertificate().hashCode()); + result = prime * result + + ((getDefaultCertificate() == null) ? 0 : getDefaultCertificate().hashCode()); return result; } @@ -751,7 +723,7 @@ public void addCertificate(Certificate cert) { if (hasCertificate(cert)) throw new AlreadyExistsException( - "Certificate '" + cert + "' is already bound to user '" + this + "'."); + "Certificate '" + cert + "' is already bound to user '" + this + "'."); getCertificates().add(cert); cert.setUser(this); @@ -772,11 +744,7 @@ public boolean hasCertificate(Certificate cert) { public Certificate getCertificate(String subject, String issuer) { for (Certificate c : certificates) { - if (c.getSubjectString() - .equals(subject) - && c.getCa() - .getSubjectString() - .equals(issuer)) + if (c.getSubjectString().equals(subject) && c.getCa().getSubjectString().equals(issuer)) return c; } @@ -789,8 +757,7 @@ public List getCertificatesBySubject(String subject) { for (Certificate c : certificates) { - if (c.getSubjectString() - .equals(subject)) + if (c.getSubjectString().equals(subject)) result.add(c); } @@ -801,7 +768,7 @@ public void removeCertificate(Certificate cert) { if (!hasCertificate(cert)) throw new NotFoundException( - "Certificate '" + cert + "' is not bound to user '" + this + "'."); + "Certificate '" + cert + "' is not bound to user '" + this + "'."); getCertificates().remove(cert); @@ -917,8 +884,7 @@ public String getEscapedDn() { if (cert == null) return null; - return cert.getSubjectString() - .replaceAll("'", "\\\\'"); + return cert.getSubjectString().replaceAll("'", "\\\\'"); } @@ -933,8 +899,7 @@ public Set getAupAcceptanceRecords() { /** * @param aupAcceptanceRecords the aupAcceptanceRecords to set */ - public void setAupAcceptanceRecords( - Set aupAcceptanceRecords) { + public void setAupAcceptanceRecords(Set aupAcceptanceRecords) { this.aupAcceptanceRecords = aupAcceptanceRecords; } @@ -943,8 +908,7 @@ public boolean hasSignedAUP(AUPVersion aupVersion) { for (AUPAcceptanceRecord r : aupAcceptanceRecords) { - if (r.getAupVersion() - .equals(aupVersion)) + if (r.getAupVersion().equals(aupVersion)) return true; } @@ -956,8 +920,7 @@ public AUPAcceptanceRecord getAUPAccceptanceRecord(AUPVersion aupVersion) { for (AUPAcceptanceRecord r : aupAcceptanceRecords) { - if (r.getAupVersion() - .equals(aupVersion)) + if (r.getAupVersion().equals(aupVersion)) return r; } @@ -1014,8 +977,7 @@ public Set getPersonalInformations() { /** * @param personalInformations the personalInformations to set */ - public void setPersonalInformations( - Set personalInformations) { + public void setPersonalInformations(Set personalInformations) { this.personalInformations = personalInformations; } @@ -1059,8 +1021,7 @@ public boolean hasInvalidAUPAcceptanceRecordForAUP(AUP aup) { return false; for (AUPAcceptanceRecord r : getAupAcceptanceRecords()) { - if (r.getAupVersion() - .equals(aup.getActiveVersion()) && !r.getValid()) + if (r.getAupVersion().equals(aup.getActiveVersion()) && !r.getValid()) return true; } @@ -1088,8 +1049,7 @@ public boolean hasPendingSignAUPTasks() { if (t instanceof SignAUPTask) { SignAUPTask aupTask = (SignAUPTask) t; - if (!aupTask.getStatus() - .equals(TaskStatus.COMPLETED)) + if (!aupTask.getStatus().equals(TaskStatus.COMPLETED)) return true; } @@ -1101,8 +1061,7 @@ public SignAUPTask getPendingSignAUPTask() { for (Task t : getTasks()) { if (t instanceof SignAUPTask) { SignAUPTask aupTask = (SignAUPTask) t; - if (!aupTask.getStatus() - .equals(TaskStatus.COMPLETED)) { + if (!aupTask.getStatus().equals(TaskStatus.COMPLETED)) { return aupTask; } } @@ -1120,8 +1079,7 @@ public boolean hasPendingSignAUPTask() { for (Task t : getTasks()) { if (t instanceof SignAUPTask) { SignAUPTask aupTask = (SignAUPTask) t; - if (!aupTask.getStatus() - .equals(TaskStatus.COMPLETED)) { + if (!aupTask.getStatus().equals(TaskStatus.COMPLETED)) { return true; } } @@ -1139,10 +1097,7 @@ public boolean hasPendingSignAUPTask(AUP aup) { if (t instanceof SignAUPTask) { SignAUPTask aupTask = (SignAUPTask) t; log.debug("aupTask: " + aupTask); - if (aupTask.getAup() - .equals(aup) - && (!aupTask.getStatus() - .equals(TaskStatus.COMPLETED))) { + if (aupTask.getAup().equals(aup) && (!aupTask.getStatus().equals(TaskStatus.COMPLETED))) { log.debug("Found pending aup task: " + aupTask); return true; } @@ -1161,10 +1116,7 @@ public SignAUPTask getPendingSignAUPTask(AUP aup) { if (t instanceof SignAUPTask) { SignAUPTask aupTask = (SignAUPTask) t; - if (aupTask.getAup() - .equals(aup) - && !aupTask.getStatus() - .equals(TaskStatus.COMPLETED)) + if (aupTask.getAup().equals(aup) && !aupTask.getStatus().equals(TaskStatus.COMPLETED)) return aupTask; } } @@ -1190,8 +1142,7 @@ public void suspend(SuspensionReason reason) { } /** - * Restores membership and certificates that where suspended for the reason - * passed as argument + * Restores membership and certificates that where suspended for the reason passed as argument * * @param reason */ @@ -1334,16 +1285,16 @@ public int compareTo(VOMSUser that) { } } - if (getDefaultCertificate() != null){ + if (getDefaultCertificate() != null) { // Both users have name and surname undefined, compare certificates return getDefaultCertificate().compareTo(that.getDefaultCertificate()); } - + // Compare by id as last resort - if (getId() != null){ + if (getId() != null) { return getId().compareTo(that.getId()); } - + return -1; } diff --git a/voms-admin-server/src/main/resources/rebel.xml b/voms-admin-server/src/main/resources/rebel.xml deleted file mode 100644 index 3b65d812..00000000 --- a/voms-admin-server/src/main/resources/rebel.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java new file mode 100644 index 00000000..d0aeecdc --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java @@ -0,0 +1,200 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static java.time.Clock.fixed; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import java.time.Instant; +import java.time.ZoneId; +import java.util.concurrent.TimeUnit; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.core.tasks.DatabaseTransactionTaskWrapper; +import org.glite.security.voms.admin.core.tasks.VOMSExecutorService; +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.integration.VOMSPluginConfigurationException; +import org.glite.security.voms.admin.integration.cern.HrDbApiService; +import org.glite.security.voms.admin.integration.cern.HrDbApiServiceFactory; +import org.glite.security.voms.admin.integration.cern.HrDbConfigurator; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.glite.security.voms.admin.integration.cern.HrDbRequestValidator; +import org.glite.security.voms.admin.integration.cern.HrDbRequestValidatorFactory; +import org.glite.security.voms.admin.integration.cern.HrDbSyncTask; +import org.glite.security.voms.admin.integration.cern.HrDbSyncTaskFactory; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +public class HrDbConfiguratorTests extends HrDbTestSupport { + + @Mock + VOMSConfiguration vomsConfig; + + @Mock + ValidationManager manager; + + @Mock + VOMSExecutorService executorService; + + @Mock + VOMSUserDAO dao; + + @Mock + HrDbApiServiceFactory apiFactory; + + @Mock + HrDbApiService api; + + @Mock + HrDbSyncTaskFactory syncTaskFactory; + + @Mock + HrDbSyncTask syncTask; + + @Mock + HrDbRequestValidatorFactory validatorFactory; + + @Mock + HrDbRequestValidator validator; + + HrDbConfigurator configurator; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + configurator = new HrDbConfigurator(vomsConfig); + configurator.setPluginName("orgdb"); + configurator.setApiServiceFactory(apiFactory); + configurator.setExecutorService(executorService); + configurator.setRequestValidatorFactory(validatorFactory); + configurator.setValidationManager(manager); + configurator.setSyncTaskFactory(syncTaskFactory); + configurator.setUserDao(dao); + configurator.setClock(CLOCK); + + when(vomsConfig.getConfigurationDirectoryPath()).thenReturn("src/test/resources/cern/config"); + when(vomsConfig.getExternalValidatorProperty(eq("orgdb"), anyString(), anyString())) + .thenReturn("src/test/resources/cern/config/orgdb.properties"); + when(apiFactory.newHrDbApiService(any())).thenReturn(api); + when(validatorFactory.newHrDbRequestValidator(any(), any())).thenReturn(validator); + when(syncTaskFactory.buildSyncTask(any(), any(), any(), any())).thenReturn(syncTask); + } + + @Test + public void testConfigurationFileIsFoundAndParsed() throws VOMSPluginConfigurationException { + configurator.configure(); + verifyZeroInteractions(executorService); + verifyZeroInteractions(syncTaskFactory); + verify(manager).setRequestValidationContext(Mockito.eq(validator)); + } + + @Test(expected = VOMSPluginConfigurationException.class) + public void testConfigurationNotFoundPrintsAppropriateErrorMessage() + throws VOMSPluginConfigurationException { + when(vomsConfig.getExternalValidatorProperty(eq("orgdb"), anyString(), anyString())) + .thenReturn("does/not/exist/orgdb.properties"); + try { + configurator.configure(); + } catch (VOMSPluginConfigurationException e) { + assertThat(e.getMessage(), + containsString("'does/not/exist/orgdb.properties' for plugin 'orgdb' does not exist!")); + throw e; + } + } + + @Test + public void testMembershipCheckTaskScheduling() throws VOMSPluginConfigurationException { + HrDbProperties props = new HrDbProperties(); + + configurator.setHrConfig(props); + configurator.configure(); + + verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), + Mockito.anyLong(), Mockito.eq(props.getMembesrshipCheck().getPeriodInSeconds()), + Mockito.eq(TimeUnit.SECONDS)); + + verify(executorService).schedule(Mockito.isA(DatabaseTransactionTaskWrapper.class), + Mockito.eq(300L), Mockito.eq(TimeUnit.SECONDS)); + } + + @Test + public void testNoStartupTaskScheduling() throws VOMSPluginConfigurationException { + HrDbProperties props = new HrDbProperties(); + + props.getMembesrshipCheck().setRunAtStartup(false); + + configurator.setHrConfig(props); + configurator.configure(); + + verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), + Mockito.eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + + verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); + } + + @Test + public void testStartupTaskSchedulingCanceled() throws VOMSPluginConfigurationException { + HrDbProperties props = new HrDbProperties(); + + props.getMembesrshipCheck().setRunAtStartup(true); + + configurator.setHrConfig(props); + configurator.setClock(fixed(Instant.parse("2019-01-01T21:45:00.00Z"), ZoneId.systemDefault())); + configurator.configure(); + + + verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), + eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + + verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); + } + + @Test + public void testStartupTaskScheduledTheNextDay() throws VOMSPluginConfigurationException { + HrDbProperties props = new HrDbProperties(); + + props.getMembesrshipCheck().setRunAtStartup(false); + props.getMembesrshipCheck().setStartHour(22); + + configurator.setHrConfig(props); + configurator.setClock(fixed(Instant.parse("2019-01-01T21:01:00.00Z"), ZoneId.systemDefault())); + configurator.configure(); + + + verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), + eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + + verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); + } + + + + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java new file mode 100644 index 00000000..ee3494b0 --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.util.Properties; + +import org.glite.security.voms.admin.integration.cern.HrDbError; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.junit.Test; + +public class HrDbPropertiesTest { + + + @Test + public void testRequiredProperties() { + + Properties props = new Properties(); + + for (String k: HrDbProperties.REQUIRED_KEYS) { + try { + + HrDbProperties.fromProperties(props); + fail("Expected error not thrown"); + + } catch (HrDbError e) { + assertThat(e.getMessage(), containsString(String.format("required property '%s' not found", k))); + props.setProperty(k, ""); + + } + } + + HrDbProperties.fromProperties(props); + } + + @Test + public void testValueParsing() { + Properties props = new Properties(); + + props.setProperty(HrDbProperties.EXPERIMENT_KEY, "atlas"); + props.setProperty(HrDbProperties.API_ENDPOINT_KEY, "http://example"); + props.setProperty(HrDbProperties.API_USERNAME_KEY, "test"); + props.setProperty(HrDbProperties.API_PASSWORD_KEY, "password"); + props.setProperty(HrDbProperties.MEMBERSHIP_CHECK_ENABLED_KEY, "false"); + props.setProperty(HrDbProperties.MEMBERSHIP_CHECK_PERIOD_KEY, "86400"); + + HrDbProperties hrConfig = HrDbProperties.fromProperties(props); + + assertThat(hrConfig.getExperimentName(), is("atlas")); + assertThat(hrConfig.getApi().getEndpoint(), is("http://example")); + assertThat(hrConfig.getApi().getUsername(), is("test")); + assertThat(hrConfig.getApi().getPassword(), is("password")); + assertThat(hrConfig.getMembesrshipCheck().isEnabled(), is(false)); + assertThat(hrConfig.getMembesrshipCheck().getPeriodInSeconds(), is(86400L)); + } + + @Test + public void testApiTimeoutChecks() { + Properties props = new Properties(); + + props.setProperty(HrDbProperties.EXPERIMENT_KEY, "atlas"); + props.setProperty(HrDbProperties.API_ENDPOINT_KEY, "http://example"); + props.setProperty(HrDbProperties.API_USERNAME_KEY, "test"); + props.setProperty(HrDbProperties.API_PASSWORD_KEY, "password"); + props.setProperty(HrDbProperties.API_TIMEOUT_KEY, "-1"); + + HrDbProperties hrConfig = HrDbProperties.fromProperties(props); + assertThat(hrConfig.getApi().getTimeoutInSeconds(), is(5L)); + + props.setProperty(HrDbProperties.API_TIMEOUT_KEY, "1"); + hrConfig = HrDbProperties.fromProperties(props); + assertThat(hrConfig.getApi().getTimeoutInSeconds(), is(1L)); + } + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java new file mode 100644 index 00000000..d90fa6af --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static java.util.Optional.empty; +import static org.glite.security.voms.admin.core.validation.RequestValidationResult.Outcome.FAILURE; +import static org.glite.security.voms.admin.core.validation.RequestValidationResult.Outcome.SUCCESS; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.glite.security.voms.admin.core.validation.RequestValidationResult; +import org.glite.security.voms.admin.integration.cern.HrDbApiService; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.glite.security.voms.admin.integration.cern.HrDbRequestValidator; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.request.NewVOMembershipRequest; +import org.glite.security.voms.admin.persistence.model.request.RequesterInfo; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class HrDbRequestValidatorTest extends HrDbTestSupport { + + @Mock + HrDbApiService apiService; + + @Mock + NewVOMembershipRequest request; + + @Mock + RequesterInfo requestor; + + @Mock + VOPersonDTO person; + + @Mock + ParticipationDTO participation; + + HrDbProperties hrConfig; + HrDbRequestValidator validator; + + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(request.getRequesterInfo()).thenReturn(requestor); + + hrConfig = new HrDbProperties(); + validator = new HrDbRequestValidator(CLOCK, hrConfig, apiService); + } + + @Test + public void testNoRecordFound() { + when(requestor.getEmailAddress()).thenReturn("test@example"); + when(apiService.getVoPersonRecordByEmail(anyString())).thenReturn(Optional.empty()); + + RequestValidationResult result = validator.validateRequest(request); + assertThat(result.getOutcome(), is(FAILURE)); + assertThat(result.getMessage(), containsString("No HR db participation found")); + } + + @Test + public void testNoValidParticipation() { + + when(requestor.getEmailAddress()).thenReturn("test@example"); + when(requestor.getName()).thenReturn("Adrienne"); + when(requestor.getSurname()).thenReturn("Lenker"); + + when(apiService.getVoPersonRecordByEmail(anyString())).thenReturn(Optional.of(person)); + when(person.getEmail()).thenReturn("test@example"); + when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); + when(person.getFirstName()).thenReturn("TEST"); + when(person.getName()).thenReturn("USER"); + when(person.findValidParticipationsForExperiment(any(), anyString())) + .thenReturn(empty()); + + + RequestValidationResult result = validator.validateRequest(request); + + assertThat(result.getOutcome(), is(FAILURE)); + assertThat(result.getMessage(), containsString("No HR db participation found")); + } + + @Test + public void testDataMismatch() { + when(requestor.getEmailAddress()).thenReturn("test@example"); + when(requestor.getName()).thenReturn("Adrienne"); + when(requestor.getSurname()).thenReturn("Lenker"); + + when(apiService.getVoPersonRecordByEmail(anyString())).thenReturn(Optional.of(person)); + when(person.getEmail()).thenReturn("test@example"); + when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); + when(person.getFirstName()).thenReturn("TEST"); + when(person.getName()).thenReturn("USER"); + when(person.findValidParticipationsForExperiment(any(), anyString())) + .thenReturn(Optional.of(participation)); + + RequestValidationResult result = validator.validateRequest(request); + assertThat(result.getOutcome(), is(FAILURE)); + assertThat(result.getMessage(), containsString("did not match the data you entered")); + + } + + @Test + public void testValidationSuccess() { + when(requestor.getEmailAddress()).thenReturn("test@example"); + when(requestor.getName()).thenReturn("Adrienne"); + when(requestor.getSurname()).thenReturn("Lenker"); + + when(apiService.getVoPersonRecordByEmail(anyString())).thenReturn(Optional.of(person)); + when(person.getEmail()).thenReturn("test@example"); + when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); + when(person.getFirstName()).thenReturn("ADRIENNE"); + when(person.getName()).thenReturn("LENKER"); + when(person.findValidParticipationsForExperiment(any(), anyString())) + .thenReturn(Optional.of(participation)); + + RequestValidationResult result = validator.validateRequest(request); + assertThat(result.getOutcome(), is(SUCCESS)); + + } + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbSyncTaskTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbSyncTaskTest.java new file mode 100644 index 00000000..0d63a52d --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDbSyncTaskTest.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static org.junit.Assert.fail; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.integration.cern.HrDbApiService; +import org.glite.security.voms.admin.integration.cern.HrDbError; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.glite.security.voms.admin.integration.cern.HrDbSyncTask; +import org.glite.security.voms.admin.integration.cern.HrDefaultHandler; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.hibernate.ScrollableResults; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + + + +public class HrDbSyncTaskTest { + + @Spy + HrDbProperties config; + + @Mock + HrDbApiService hrDbApi; + + @Mock + VOMSConfiguration vomsConfig; + + @Mock + VOMSUserDAO dao; + + @Mock + ScrollableResults results; + + @Spy + VOMSUser user1; + + @Spy + VOMSUser user2; + + @Spy + VOPersonDTO person1; + + @Mock + HrDefaultHandler handler; + + HrDbSyncTask task; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + task = new HrDbSyncTask(config, hrDbApi, dao, vomsConfig); + + task.setMissingRecordHandler(handler); + task.setSyncHandler(handler); + + config.setExperimentName("experiment"); + + when(dao.findAllWithCursor()).thenReturn(results); + when(results.next()).thenReturn(true, true, false); + when(results.get(0)).thenReturn(user1, user2); + + user1.setId(1L); + user1.setName("test"); + user1.setSurname("user"); + user1.setEmailAddress("test.user@example"); + + user2.setId(2L); + user2.setName("tost"); + user2.setSurname("aser"); + user2.setEmailAddress("tost.aser@example"); + + when(hrDbApi.lookupVomsUser(user1)).thenReturn(Optional.of(person1)); + when(hrDbApi.lookupVomsUser(user2)).thenReturn(Optional.empty()); + } + + + @Test + public void testSync() { + + task.run(); + + verify(handler).synchronizeMembershipInformation(user1, person1); + verify(handler).handleMissingHrRecord(user2); + + + } + + @Test + public void testApiError() { + + when(hrDbApi.lookupVomsUser(user1)).thenThrow(new HrDbError("Sync error")); + + task.run(); + + verify(handler).handleMissingHrRecord(user2); + + } + + @Test + public void testOtherError() { + + when(hrDbApi.lookupVomsUser(user1)).thenThrow(new NullPointerException()); + + try { + task.run(); + fail("Expected exception caught!"); + } catch (NullPointerException e) { + + } + + verify(handler, Mockito.times(0)).synchronizeMembershipInformation(user1, person1); + verify(handler, Mockito.times(0)).handleMissingHrRecord(user2); + + } + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java b/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java new file mode 100644 index 00000000..0468142f --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static utils.TestFileUtils.readFile; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; + +public class HrDbTestSupport { + + public static final Instant NOW = Instant.parse("2019-01-01T00:00:00.00Z"); + + public static final Instant TWO_YEARS_AGO = NOW.minus(730, ChronoUnit.DAYS); + public static final Instant ONE_YEAR_AGO = NOW.minus(365, ChronoUnit.DAYS); + public static final Instant ONE_WEEK_AGO = NOW.minus(7, ChronoUnit.DAYS); + + public static final Instant A_DAY_AGO = NOW.minus(1, ChronoUnit.DAYS); + + public static final Instant ONE_WEEK_FROM_NOW = NOW.plus(7, ChronoUnit.DAYS); + public static final Instant ONE_YEAR_FROM_NOW = NOW.plus(365, ChronoUnit.DAYS); + + public static final Clock CLOCK = Clock.fixed(NOW, ZoneId.systemDefault()); + + public static final String VO_PERSON_1_JSON_PATH = "src/test/resources/cern/json/voPerson1.json"; + public static final String VO_PERSON_1_JSON = readFile(VO_PERSON_1_JSON_PATH); + + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java new file mode 100644 index 00000000..6cf441de --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.verify; + +import java.util.Date; + +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.glite.security.voms.admin.integration.cern.HrDefaultHandler; +import org.glite.security.voms.admin.integration.cern.dto.InstituteDTO; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.glite.security.voms.admin.persistence.model.VOMSUser.SuspensionReason; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +import com.google.common.collect.Sets; + +public class HrDefaultHandlerTest extends HrDbTestSupport { + + @Spy + HrDbProperties properties = new HrDbProperties(); + + @Mock + ValidationManager manager; + + @Spy + VOMSUser user = new VOMSUser(); + + @Spy + VOPersonDTO voPerson = new VOPersonDTO(); + + @Spy + ParticipationDTO oneParticipation = new ParticipationDTO(); + + @Spy + ParticipationDTO anotherParticipation = new ParticipationDTO(); + + @Spy + ParticipationDTO aThirdParticipation = new ParticipationDTO(); + + @Spy + InstituteDTO institute = new InstituteDTO(); + + HrDefaultHandler handler; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + handler = new HrDefaultHandler(CLOCK, properties, manager); + + properties.setExperimentName("experiment"); + + institute.setId("institute-id"); + institute.setName("Institute"); + + user.setId(1L); + user.setName("test"); + user.setSurname("user"); + user.setOrgDbId(-1L); + + voPerson.setId(1L); + + voPerson.setFirstName("TEST"); + voPerson.setName("USER"); + voPerson.setEmail("TEST.USER@CNAF.INFN.IT"); + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_WEEK_AGO)); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + } + + + @Test + public void testMissingHrRecordLeadsToUserSuspension() { + + handler.handleMissingHrRecord(user); + + SuspensionReason reason = SuspensionReason.HR_DB_VALIDATION; + reason.setMessage("OrgDB: No record found"); + + verify(manager).suspendUser(Mockito.eq(user), Mockito.eq(reason)); + + } + + @Test + public void testSynchStrategy() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_WEEK_AGO)); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + assertThat(user.getEndTime(), nullValue()); + + + } + + @Test + public void testSynchInvalidParticipation() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); + oneParticipation.setEndDate(Date.from(ONE_WEEK_AGO)); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + assertThat(user.getEndTime(), is(Date.from(NOW))); + } + + @Test + public void testDoNotRestoreSuspendedUserForOtherReason() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); + + user.setSuspended(true); + user.setSuspensionReason(SuspensionReason.FAILED_TO_SIGN_AUP.getMessage()); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + + assertThat(user.isSuspended(), is(true)); + } + + @Test + public void testRestoreSuspendedUserDoToValidationError() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); + + user.setSuspended(true); + user.setSuspensionReasonCode(SuspensionReason.HR_DB_VALIDATION); + user.setSuspensionReason(SuspensionReason.HR_DB_VALIDATION.getMessage()); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + + verify(manager).restoreUser(Mockito.eq(user)); + + + } + + @Test + public void testRestoreSuspendedUserDoToMembershipExpiration() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); + + user.setSuspended(true); + user.setSuspensionReasonCode(SuspensionReason.MEMBERSHIP_EXPIRATION); + + user.setSuspensionReason(SuspensionReason.MEMBERSHIP_EXPIRATION.getMessage()); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + + verify(manager).restoreUser(Mockito.eq(user)); + + + } + + +} diff --git a/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java b/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java new file mode 100644 index 00000000..03542db7 --- /dev/null +++ b/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java @@ -0,0 +1,303 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package integration.hr; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertThat; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.matchers.Times.exactly; +import static org.mockserver.matchers.Times.once; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; +import static utils.TestSocketUtils.findAvailableTcpPort; + +import java.util.Optional; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.glite.security.voms.admin.integration.cern.HrDbError; +import org.glite.security.voms.admin.integration.cern.HrDbProperties; +import org.glite.security.voms.admin.integration.cern.HttpClientHrDbApiService; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpError; +import org.mockserver.model.HttpResponse; + +public class HttpClientIntegrationTest extends HrDbTestSupport{ + + private static int port; + private static ClientAndServer mockServer; + + HrDbProperties properties; + HttpClientHrDbApiService apiService; + + @BeforeClass + public static void startMockServer() { + port = findAvailableTcpPort(); + mockServer = startClientAndServer(port); + } + + @AfterClass + public static void stopMockServer() { + mockServer.stop(); + } + + @Before + public void setup() { + properties = new HrDbProperties(); + properties.setExperimentName("cms"); + properties.getApi().setEndpoint("http://localhost:" + port); + properties.getApi().setUsername("user"); + properties.getApi().setPassword("password"); + properties.getApi().setTimeoutInSeconds(1L); + + apiService = new HttpClientHrDbApiService(CLOCK, properties); + } + + @After + public void teardown() { + mockServer.reset(); + } + + + @Test(expected = HrDbError.class) + public void testVoPersonAuthNErrorHandling() { + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) + .respond(HttpResponse.response().withStatusCode(403)); + + try { + apiService.getVoPersonRecord(1); + + } catch (HrDbError e) { + + assertThat(e.getMessage(), containsString("403")); + mockServer.verify(request("/api/VOPersons/1").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + throw e; + } + } + + @Test(expected = HrDbError.class) + public void testTimeoutEnforced() { + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) + .respond(HttpResponse.response().withStatusCode(404).withDelay(TimeUnit.SECONDS, 2)); + + try { + apiService.getVoPersonRecord(1); + + } catch (HrDbError e) { + + assertThat(e.getMessage(), containsString("request timeout exceeded")); + throw e; + } + } + + @Test(expected = HrDbError.class) + public void testDropConnectionError() { + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) + .error(HttpError.error().withDropConnection(true));; + + try { + apiService.getVoPersonRecord(1); + + } catch (HrDbError e) { + + assertThat(e.getMessage(), is("Error contacting the HR DB api")); + throw e; + } + } + + + @Test(expected = HrDbError.class) + public void testRandomBytesResponse() { + + byte[] randomByteArray = new byte[25]; + new Random().nextBytes(randomByteArray); + + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) + .error(HttpError.error().withResponseBytes(randomByteArray));; + + try { + apiService.getVoPersonRecord(1); + + } catch (HrDbError e) { + + assertThat(e.getMessage(), is("Error contacting the HR DB api")); + throw e; + } + } + + @Test + public void testGetPersonSuccess() { + + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) + .respond(response(VO_PERSON_1_JSON)); + + Optional voPerson = apiService.getVoPersonRecord(1); + + mockServer.verify(request("/api/VOPersons/1").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + + assertThat(voPerson.isPresent(), is(true)); + assertThat(voPerson.get().getId(), is(1L)); + assertThat(voPerson.get().getName(), is("MARPLE")); + assertThat(voPerson.get().getFirstName(), is("IRWIN")); + assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); + assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); + assertThat(voPerson.get().getParticipations(), hasSize(1)); + + ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); + + assertThat(participation.getExperiment(), is("ATLAS")); + assertThat(participation.getStartDate(), notNullValue()); + assertThat(participation.getEndDate(), notNullValue()); + assertThat(participation.isValidAtInstant(NOW), is(true)); + + assertThat(participation.getInstitute(), notNullValue()); + assertThat(participation.getInstitute().getName(), is("Institute 35")); + assertThat(participation.getInstitute().getId(), is("000035")); + assertThat(participation.getInstitute().getTown(), is("Some place 35")); + assertThat(participation.getInstitute().getCountry(), is("IT")); + } + + @Test + public void testGetPersonByEmailSuccess() { + + mockServer + .when(request("/api/VOPersons/email/IRWIN.MARPLE.1@mail.example").withMethod("GET"), once()) + .respond(response(VO_PERSON_1_JSON)); + + Optional voPerson = + apiService.getVoPersonRecordByEmail("IRWIN.MARPLE.1@mail.example"); + + mockServer.verify(request("/api/VOPersons/email/IRWIN.MARPLE.1@mail.example").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + + assertThat(voPerson.isPresent(), is(true)); + assertThat(voPerson.get().getId(), is(1L)); + assertThat(voPerson.get().getName(), is("MARPLE")); + assertThat(voPerson.get().getFirstName(), is("IRWIN")); + assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); + assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); + assertThat(voPerson.get().getParticipations(), hasSize(1)); + + ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); + + assertThat(participation.getExperiment(), is("ATLAS")); + assertThat(participation.getStartDate(), notNullValue()); + assertThat(participation.getEndDate(), notNullValue()); + assertThat(participation.isValidAtInstant(NOW), is(true)); + + assertThat(participation.getInstitute(), notNullValue()); + assertThat(participation.getInstitute().getName(), is("Institute 35")); + assertThat(participation.getInstitute().getId(), is("000035")); + assertThat(participation.getInstitute().getTown(), is("Some place 35")); + assertThat(participation.getInstitute().getCountry(), is("IT")); + } + + @Test + public void testHasValidExperimentParticipationSuccess() { + mockServer.when(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET"), once()) + .respond(response("true")); + + assertThat(apiService.hasValidExperimentParticipation(1), is(true)); + mockServer.verify(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + + + } + + @Test + public void testHasValidExperimentParticipationByEmailSuccess() { + + mockServer + .when(request("/api/VOPersons/email/IRWIN.MARPLE.1@mail.example").withMethod("GET"), once()) + .respond(response(VO_PERSON_1_JSON)); + + assertThat(apiService.hasValidExperimentParticipationByEmail("IRWIN.MARPLE.1@mail.example"), + is(true)); + + mockServer.verify(request("/api/VOPersons/email/IRWIN.MARPLE.1@mail.example").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + } + + @Test + public void testGetPersonByVomsUser() { + + mockServer.when(request("/api/VOPersons/1").withMethod("GET"), exactly(2)) + .respond(response(VO_PERSON_1_JSON)); + + mockServer.when(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET"), once()) + .respond(response("true")); + + VOMSUser user = new VOMSUser(); + user.setId(1L); + user.setOrgDbId(1L); + + Optional voPerson = apiService.lookupVomsUser(user); + + assertThat(voPerson.isPresent(), is(true)); + assertThat(voPerson.get().getId(), is(1L)); + assertThat(voPerson.get().getName(), is("MARPLE")); + assertThat(voPerson.get().getFirstName(), is("IRWIN")); + assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); + assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); + assertThat(voPerson.get().getParticipations(), hasSize(1)); + + ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); + + assertThat(participation.getExperiment(), is("ATLAS")); + assertThat(participation.getStartDate(), notNullValue()); + assertThat(participation.getEndDate(), notNullValue()); + assertThat(participation.isValidAtInstant(NOW), is(true)); + + assertThat(participation.getInstitute(), notNullValue()); + assertThat(participation.getInstitute().getName(), is("Institute 35")); + assertThat(participation.getInstitute().getId(), is("000035")); + assertThat(participation.getInstitute().getTown(), is("Some place 35")); + assertThat(participation.getInstitute().getCountry(), is("IT")); + + mockServer.verify(request("/api/VOPersons/1").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + + assertThat(apiService.hasValidExperimentParticipation(user), is(true)); + + mockServer.verify(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET") + .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); + + } + + @Test + public void testGetPersonByVomsUserNoOrgId() { + + VOMSUser user = new VOMSUser(); + user.setId(1L); + + assertThat(apiService.lookupVomsUser(user).isPresent(), is(false)); + mockServer.verifyZeroInteractions(); + } + +} diff --git a/voms-admin-server/src/test/java/utils/TestFileUtils.java b/voms-admin-server/src/test/java/utils/TestFileUtils.java new file mode 100644 index 00000000..ac5f28a5 --- /dev/null +++ b/voms-admin-server/src/test/java/utils/TestFileUtils.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package utils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class TestFileUtils { + + private TestFileUtils() {} + + + public static String readFile(String path) { + try { + return new String(Files.readAllBytes(Paths.get(path))); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + } + +} diff --git a/voms-admin-server/src/test/java/utils/TestSocketUtils.java b/voms-admin-server/src/test/java/utils/TestSocketUtils.java new file mode 100644 index 00000000..0e262649 --- /dev/null +++ b/voms-admin-server/src/test/java/utils/TestSocketUtils.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package utils; + +import java.io.IOException; +import java.net.ServerSocket; + +public class TestSocketUtils { + + private TestSocketUtils() { + // TODO Auto-generated constructor stub + } + + public static int findAvailableTcpPort() { + try (ServerSocket socket = new ServerSocket(0)) { + socket.setReuseAddress(true); + return socket.getLocalPort(); + } catch (IOException e) { + throw new AssertionError(e.getMessage()); + } + } + +} diff --git a/voms-admin-server/src/test/resources/cern/config/orgdb.properties b/voms-admin-server/src/test/resources/cern/config/orgdb.properties new file mode 100644 index 00000000..6acd3505 --- /dev/null +++ b/voms-admin-server/src/test/resources/cern/config/orgdb.properties @@ -0,0 +1,7 @@ + experiment=cms + membership_check.period=600 + membership_check.enabled=false + api.endpoint=http://localhost:8080 + api.username=user + api.password=password + api.timeout_secs=2 \ No newline at end of file diff --git a/voms-admin-server/src/test/resources/cern/json/voPerson1.json b/voms-admin-server/src/test/resources/cern/json/voPerson1.json new file mode 100644 index 00000000..c19061e9 --- /dev/null +++ b/voms-admin-server/src/test/resources/cern/json/voPerson1.json @@ -0,0 +1,20 @@ +{ + "id": 1, + "name": "MARPLE", + "firstName": "IRWIN", + "email": "IRWIN.MARPLE.1@mail.example", + "physicalEmail": "MARPLE.1@cern.ch", + "participations": [ + { + "institute": { + "id": "000035", + "name": "Institute 35", + "town": "Some place 35", + "country": "IT" + }, + "experiment": "ATLAS", + "startDate": "2008-02-05", + "endDate": "2022-01-01" + } + ] +} \ No newline at end of file diff --git a/voms-container/src/main/resources/rebel.xml b/voms-container/src/main/resources/rebel.xml deleted file mode 100644 index e3748d21..00000000 --- a/voms-container/src/main/resources/rebel.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - From 5c42e2a08c07faf98f253f367101771fa85598f7 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 17 Dec 2019 19:31:50 +0100 Subject: [PATCH 35/63] Work around commons-io jar hell CANL wants commons-io-1.3.2. The latest struts, and in particular the fileupload functionality, requires commons-io-2.2. With 1.3.2 fileupload fails (some class looks for a method that is not available in 1.3.2). When using 2.2, CANL connector startup fails, since a method CANL relies on was removed in 2.2. So the workaround is to use commons-io-1.3.2 for the container and commons-io-2.2 inside the voms-admin war, which however required some gymnastics in the build configuration. --- pom.xml | 4 ++++ voms-admin-server/pom.xml | 7 +++++++ voms-admin-server/resources/jars/README.md | 11 +++++++++++ .../resources/jars/commons-io-1.3.2.jar | Bin 0 -> 87776 bytes voms-admin-server/src/assemble/tarball.xml | 10 ++++++++++ voms-container/pom.xml | 5 +++++ 6 files changed, 37 insertions(+) create mode 100644 voms-admin-server/resources/jars/README.md create mode 100644 voms-admin-server/resources/jars/commons-io-1.3.2.jar diff --git a/pom.xml b/pom.xml index e6a480f3..fd72ead9 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,9 @@ 8.1.9.v20130131 + 1.1 2.11 21.0 @@ -82,11 +84,13 @@ test + org.slf4j diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 624a3351..1f3ef2bd 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -45,6 +45,7 @@ 2.2.2 3.2 5.5.1 + 2.2 @@ -170,6 +171,12 @@ + + commons-io + commons-io + ${commons-io.version} + + org.italiangrid voms-admin-api diff --git a/voms-admin-server/resources/jars/README.md b/voms-admin-server/resources/jars/README.md new file mode 100644 index 00000000..ec7c1508 --- /dev/null +++ b/voms-admin-server/resources/jars/README.md @@ -0,0 +1,11 @@ +Embedding the commons-io 1.3.2 jar here since we have a jar conflict. + +The voms-container (and canl) require 1.3.2 to work properly, while the latest +struts (and in particular the fileupload functionality used for certificate +upload) requires version 2.2. + +Things seem to work fine if 2.2 is embedded in the war, while 1.3.2 is in the +classpath of the voms-container jar, but since maven doesn't allow to manage +multiple versions of a dependency in the build of a component, and the tarball +is build in the voms-admin-server component, the easiest way of including the +1.3.2 jar in the tarball is by explicitly include the file from this directory. diff --git a/voms-admin-server/resources/jars/commons-io-1.3.2.jar b/voms-admin-server/resources/jars/commons-io-1.3.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..865c9e41cee5e3f65a734965aa1c2699b069b08e GIT binary patch literal 87776 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

A6&xXLJ)&33psjUNK4JvEVm%t&{TCAh!T;B+qd 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 literal 0 HcmV?d00001 diff --git a/voms-admin-server/src/assemble/tarball.xml b/voms-admin-server/src/assemble/tarball.xml index 8234b630..3c8dc365 100644 --- a/voms-admin-server/src/assemble/tarball.xml +++ b/voms-admin-server/src/assemble/tarball.xml @@ -81,6 +81,15 @@ 0755 + + + resources/jars + /var/lib/voms-admin/lib + + commons-io-1.3.2.jar + + 0644 + @@ -92,6 +101,7 @@ org.italiangrid:voms-container + commons-io:commons-io diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 2c5909e5..69b5f271 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -31,6 +31,10 @@ VOMS Jetty Container + + 1.3.2 + + @@ -112,6 +116,7 @@ commons-io commons-io + ${commons-io.version} From f20d7c380b9e23376a7a89878903fd9053912a02 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 20 Dec 2019 07:33:55 +0100 Subject: [PATCH 36/63] Restrict information shown to unprivileged users First steps towards limiting information shown to unprivileged users. Rationale: - certificates info is still shown, as requested - suspension status details and personal information are hidden, and only shown to clients having personal information access privileges - the search for unprivileged users is limited on certificate subjects/issuers The view and the restful APIs have been modified to behave as described above. --- .../voms/admin/apiv2/JSONSerializer.java | 27 +- .../voms/admin/apiv2/VOMSUserJSON.java | 2 +- .../groups/SearchMembersOperation.java | 58 ++-- .../users/SearchUsersOperation.java | 23 +- .../admin/persistence/dao/SearchUtils.java | 49 +++ .../admin/persistence/dao/VOMSGroupDAO.java | 317 ++++++++---------- .../admin/persistence/dao/VOMSRoleDAO.java | 206 ++++++------ .../admin/persistence/dao/VOMSUserDAO.java | 84 ++--- .../view/actions/apiv2/UserInfoAction.java | 2 +- .../admin/view/actions/apiv2/UsersAction.java | 2 +- .../webapp/WEB-INF/p/group/groupDetail.jsp | 127 ++----- .../webapp/WEB-INF/p/group/searchMember.jsp | 102 +----- .../webapp/WEB-INF/p/role/searchMember.jsp | 187 +++-------- .../webapp/WEB-INF/p/user/certificates.jsp | 15 +- .../webapp/WEB-INF/p/user/requestHistory.jsp | 4 +- .../WEB-INF/p/user/suspensionDetail.jsp | 3 +- .../main/webapp/WEB-INF/p/user/userDetail.jsp | 176 +++------- .../main/webapp/WEB-INF/p/user/userInfo.jsp | 74 ++-- .../src/main/webapp/WEB-INF/p/user/users.jsp | 186 +++------- .../src/main/webapp/style/style.css | 4 +- 20 files changed, 655 insertions(+), 993 deletions(-) create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/SearchUtils.java diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/JSONSerializer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/JSONSerializer.java index c840a784..5fae36cd 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/JSONSerializer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/JSONSerializer.java @@ -25,15 +25,16 @@ public class JSONSerializer { - private static final VOMSPermission VO_ATTRIBUTE_READ_PERMISSIONS = VOMSPermission - .getEmptyPermissions().setAttributesReadPermission(); + private static final VOMSPermission VO_ATTRIBUTE_READ_PERMISSIONS = + VOMSPermission.getEmptyPermissions().setAttributesReadPermission(); - private static final VOMSPermission VO_MEMBERSHIP_READ_PERMISSIONS = VOMSPermission - .getEmptyPermissions().setMembershipReadPermission() - .setContainerReadPermission(); + private static final VOMSPermission VO_MEMBERSHIP_READ_PERMISSIONS = + VOMSPermission.getEmptyPermissions() + .setMembershipReadPermission() + .setContainerReadPermission(); - private static final VOMSPermission PI_READ_PERMISSIONS = VOMSPermission - .getEmptyPermissions().setPersonalInfoReadPermission(); + private static final VOMSPermission PI_READ_PERMISSIONS = + VOMSPermission.getEmptyPermissions().setPersonalInfoReadPermission(); public static VOMSUserJSON serialize(VOMSUser user) { @@ -56,16 +57,22 @@ public static VOMSUserJSON serialize(VOMSUser user) { json.attributesFrom(user); } - if (admin.hasPermissions(VOMSContext.getVoContext(), - VO_MEMBERSHIP_READ_PERMISSIONS)) { + if (admin.hasPermissions(VOMSContext.getVoContext(), VO_MEMBERSHIP_READ_PERMISSIONS)) { json.fqansFrom(user); } if (admin.hasPermissions(VOMSContext.getVoContext(), PI_READ_PERMISSIONS)) { json.personalInformationFrom(user); json.cernHrIdFrom(user); + } else { + + // filter out certificate details (suspension status & creation dates) + json.getCertificates().forEach(c -> { + c.setCreationTime(null); + c.setSuspended(null); + c.setSuspensionReason(null); + }); } - } return json; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/VOMSUserJSON.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/VOMSUserJSON.java index d2e98eb5..378d0468 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/VOMSUserJSON.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/apiv2/VOMSUserJSON.java @@ -58,7 +58,7 @@ public class VOMSUserJSON { Date endTime; - Boolean suspended = false; + Boolean suspended; SuspensionReason suspensionReasonCode; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/groups/SearchMembersOperation.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/groups/SearchMembersOperation.java index c0d48152..fd85d684 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/groups/SearchMembersOperation.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/groups/SearchMembersOperation.java @@ -16,7 +16,9 @@ package org.glite.security.voms.admin.operations.groups; import org.glite.security.voms.admin.operations.BaseMemberhipReadOperation; +import org.glite.security.voms.admin.operations.CurrentAdmin; import org.glite.security.voms.admin.operations.VOMSContext; +import org.glite.security.voms.admin.operations.VOMSPermission; import org.glite.security.voms.admin.persistence.dao.VOMSGroupDAO; import org.glite.security.voms.admin.persistence.dao.VOMSRoleDAO; import org.glite.security.voms.admin.persistence.model.VOMSGroup; @@ -25,11 +27,14 @@ public class SearchMembersOperation extends BaseMemberhipReadOperation { + public static final VOMSPermission PERSONAL_INFO_READ = + VOMSPermission.getEmptyPermissions().setPersonalInfoReadPermission(); + int firstResult = 0, maxResults = 0; String searchString; - private SearchMembersOperation(VOMSContext c, String searchString, - int firstResult, int maxResults) { + private SearchMembersOperation(VOMSContext c, String searchString, int firstResult, + int maxResults) { super(c); @@ -38,8 +43,8 @@ private SearchMembersOperation(VOMSContext c, String searchString, this.searchString = searchString; } - private SearchMembersOperation(VOMSGroup g, VOMSRole r, String searchString, - int firstResult, int maxResults) { + private SearchMembersOperation(VOMSGroup g, VOMSRole r, String searchString, int firstResult, + int maxResults) { super(VOMSContext.instance(g, r)); @@ -52,34 +57,45 @@ private SearchMembersOperation(VOMSGroup g, VOMSRole r, String searchString, protected Object doExecute() { - if (!__context.isGroupContext()) - return VOMSRoleDAO.instance().searchMembers(__context.getGroup(), - __context.getRole(), searchString, firstResult, maxResults); - - return VOMSGroupDAO.instance().searchMembers(__context.getGroup(), - searchString, firstResult, maxResults); - + if (CurrentAdmin.instance().hasPermissions(VOMSContext.getVoContext(), PERSONAL_INFO_READ)) { + if (!__context.isGroupContext()) { + return VOMSRoleDAO.instance() + .searchMembers(__context.getGroup(), __context.getRole(), searchString, firstResult, + maxResults); + } else { + return VOMSGroupDAO.instance() + .searchMembers(__context.getGroup(), searchString, firstResult, maxResults); + } + } else { + + if (!__context.isGroupContext()) { + return VOMSRoleDAO.instance() + .searchMemberBySubject(__context.getGroup(), __context.getRole(), searchString, + firstResult, maxResults); + + } else { + return VOMSGroupDAO.instance() + .searchMembersBySubject(__context.getGroup(), searchString, firstResult, maxResults); + } + } } - public static SearchMembersOperation instance(VOMSGroup g, VOMSRole r, - String searchString, int firstResult, int maxResults) { + public static SearchMembersOperation instance(VOMSGroup g, VOMSRole r, String searchString, + int firstResult, int maxResults) { - return new SearchMembersOperation(g, r, searchString, firstResult, - maxResults); + return new SearchMembersOperation(g, r, searchString, firstResult, maxResults); } - public static SearchMembersOperation instance(VOMSGroup g, - String searchString, int firstResult, int maxResults) { + public static SearchMembersOperation instance(VOMSGroup g, String searchString, int firstResult, + int maxResults) { - return new SearchMembersOperation(g, null, searchString, firstResult, - maxResults); + return new SearchMembersOperation(g, null, searchString, firstResult, maxResults); } public static SearchMembersOperation instance(SearchData sd) { VOMSContext ctxt = VOMSContext.instance(sd.getGroupId(), sd.getRoleId()); - return new SearchMembersOperation(ctxt, sd.getText(), sd.getFirstResult(), - sd.getMaxResults()); + return new SearchMembersOperation(ctxt, sd.getText(), sd.getFirstResult(), sd.getMaxResults()); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/SearchUsersOperation.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/SearchUsersOperation.java index 18366017..8223984b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/SearchUsersOperation.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/SearchUsersOperation.java @@ -16,8 +16,10 @@ package org.glite.security.voms.admin.operations.users; import org.glite.security.voms.admin.operations.BaseVoReadOperation; +import org.glite.security.voms.admin.operations.CurrentAdmin; import org.glite.security.voms.admin.operations.VOMSContext; import org.glite.security.voms.admin.operations.VOMSPermission; +import org.glite.security.voms.admin.operations.groups.SearchMembersOperation; import org.glite.security.voms.admin.persistence.dao.SearchResults; import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; @@ -29,8 +31,7 @@ public class SearchUsersOperation extends BaseVoReadOperation { private int maxResults; - private SearchUsersOperation(String searchString, int firstResult, - int maxResults) { + private SearchUsersOperation(String searchString, int firstResult, int maxResults) { this.searchString = searchString; this.firstResult = firstResult; @@ -40,19 +41,25 @@ private SearchUsersOperation(String searchString, int firstResult, public SearchResults doExecute() { - return VOMSUserDAO.instance().search(searchString, firstResult, maxResults); + if (CurrentAdmin.instance() + .hasPermissions(VOMSContext.getVoContext(), SearchMembersOperation.PERSONAL_INFO_READ)) { + return VOMSUserDAO.instance().search(searchString, firstResult, maxResults); + } else { + + return VOMSUserDAO.instance().searchBySubject(searchString, firstResult, maxResults); + } } - public static SearchUsersOperation instance(String searchString, - int firstResult, int maxResults) { + public static SearchUsersOperation instance(String searchString, int firstResult, + int maxResults) { return new SearchUsersOperation(searchString, firstResult, maxResults); } protected void setupPermissions() { - addRequiredPermission(VOMSContext.getVoContext(), VOMSPermission - .getContainerReadPermission().setMembershipReadPermission()); + addRequiredPermission(VOMSContext.getVoContext(), + VOMSPermission.getContainerReadPermission().setMembershipReadPermission()); } - + } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/SearchUtils.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/SearchUtils.java new file mode 100644 index 00000000..25419e3f --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/SearchUtils.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.persistence.dao; + +import org.hibernate.Query; + +@SuppressWarnings("deprecation") +public class SearchUtils { + + private SearchUtils() {} + + + @SuppressWarnings({"rawtypes"}) + public static SearchResults paginatedFind(Query q, Query countQuery, String searchString, + int firstResults, int maxResults) { + + SearchResults res = SearchResults.instance(); + + res.setSearchString(searchString); + + q.setFirstResult(firstResults); + q.setMaxResults(maxResults); + + res.setResults(q.list()); + + Long count = (Long) countQuery.uniqueResult(); + + res.setCount(count.intValue()); + + res.setFirstResult(firstResults); + res.setResultsPerPage(maxResults); + + return res; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSGroupDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSGroupDAO.java index 0b4736a1..0ea4279c 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSGroupDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSGroupDAO.java @@ -15,9 +15,10 @@ */ package org.glite.security.voms.admin.persistence.dao; +import static org.glite.security.voms.admin.persistence.dao.SearchUtils.paginatedFind; + import java.util.Iterator; import java.util.List; -import java.util.Set; import org.glite.security.voms.admin.configuration.VOMSConfiguration; import org.glite.security.voms.admin.configuration.VOMSConfigurationConstants; @@ -55,8 +56,7 @@ public List getAll() { String query = "from VOMSGroup order by name asc"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); @SuppressWarnings("unchecked") List res = q.list(); @@ -68,7 +68,8 @@ public int countMatches(String searchString) { String sString = "%" + searchString + "%"; - String cQueryString = "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString"; + String cQueryString = + "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString"; Long totalMatches = (Long) HibernateFactory.getSession() .createQuery(cQueryString) @@ -82,8 +83,7 @@ public int countMatches(String searchString) { public int countGroups() { Long count = (Long) HibernateFactory.getSession() - .createQuery( - "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup") + .createQuery("select count(*) from org.glite.security.voms.admin.persistence.model.VOMSGroup") .uniqueResult(); return count.intValue(); @@ -93,8 +93,7 @@ public int countGroups() { public List findAllWithoutRootGroup() { String query = "from VOMSGroup g where g != g.parent"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); return q.list(); } @@ -103,8 +102,7 @@ public List findAll() { String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); return q.list(); @@ -114,10 +112,10 @@ public SearchResults getAll(int firstResult, int maxResults) { SearchResults results = SearchResults.instance(); - String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup order by name asc"; + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSGroup order by name asc"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); q.setFirstResult(firstResult); q.setMaxResults(maxResults); @@ -132,21 +130,19 @@ public SearchResults getAll(int firstResult, int maxResults) { return results; } - public SearchResults search(String searchString, int firstResult, - int maxResults) { + public SearchResults search(String searchString, int firstResult, int maxResults) { - if (searchString == null || searchString.equals("") - || searchString.length() == 0) + if (searchString == null || searchString.equals("") || searchString.length() == 0) return getAll(firstResult, maxResults); SearchResults results = SearchResults.instance(); String sString = "%" + searchString + "%"; - String queryString = "from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString order by name asc"; + String queryString = + "from org.glite.security.voms.admin.persistence.model.VOMSGroup where name like :searchString order by name asc"; - Query q = HibernateFactory.getSession() - .createQuery(queryString) - .setString("searchString", sString); + Query q = + HibernateFactory.getSession().createQuery(queryString).setString("searchString", sString); q.setFirstResult(firstResult); q.setMaxResults(maxResults); @@ -163,35 +159,22 @@ public SearchResults search(String searchString, int firstResult, } - public SearchResults getMembers(VOMSGroup g, int firstResult, - int maxResults) { - - Set groupMembers = g.getMembers(); - // int count = g.getMembers().size(); // Maybe the HQL query is more - // efficient - - int count = groupMembers.size(); - - SearchResults results = SearchResults.instance(); - - String queryString = "select m.user as user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role is null"; + public SearchResults getMembers(VOMSGroup g, int firstResult, int maxResults) { + + String commonQuery = + "from VOMSMapping m where m.group = :group and m.role is null"; Query q = HibernateFactory.getSession() - .createQuery(queryString) + .createQuery(String.format("select distinct m.user as user %s", commonQuery)) .setFirstResult(firstResult) .setMaxResults(maxResults); + + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct m.user) %s", commonQuery)); q.setEntity("group", g); - - List res = q.list(); - - results.setSearchString(null); - results.setResults(res); - results.setCount(count); - results.setFirstResult(firstResult); - results.setResultsPerPage(maxResults); - - return results; + count.setEntity("group", g); + return paginatedFind(q, count, null, firstResult, maxResults); } @@ -202,79 +185,85 @@ public int countMatchingMembers(VOMSGroup g, String searchString) { String sString = "%" + searchString + "%"; - String queryString = "select count(m.user) as u from VOMSMapping m join m.user.certificates as cert where " - + "m.group = :group and m.role is null and " - + "(cert.subjectString like :searchString " - + "or cert.ca.subjectString like :searchString " - + "or m.user.name like :searchString " - + "or m.user.surname like :searchString " - + "or m.user.emailAddress like :searchString " - + "or m.user.institution like :searchString)"; - - // String queryString = - // "select count(m.user) from - // org.glite.security.voms.admin.persistence.model.VOMSMapping m where - // m.group = :group and m.role is null "+ - // "and m.user.dn like :searchString"; + String queryString = + "select count(m.user) as u from VOMSMapping m join m.user.certificates as cert where " + + "m.group = :group and m.role is null and " + "(cert.subjectString like :searchString " + + "or cert.ca.subjectString like :searchString " + "or m.user.name like :searchString " + + "or m.user.surname like :searchString " + "or m.user.emailAddress like :searchString " + + "or m.user.institution like :searchString)"; - Query q = HibernateFactory.getSession() - .createQuery(queryString) - .setString("searchString", sString); + Query q = + HibernateFactory.getSession().createQuery(queryString).setString("searchString", sString); q.setEntity("group", g); return ((Long) q.uniqueResult()).intValue(); } - - public SearchResults searchMembers(VOMSGroup g, String searchString, - int firstResult, int maxResults) { + + public SearchResults searchMembersBySubject(VOMSGroup g, String searchString, int firstResult, + int maxResults) { if (g == null) throw new NullArgumentException("Cannot search members in a null group!"); - if (searchString == null || searchString.equals("") - || searchString.length() == 0) + if (searchString == null || searchString.equals("") || searchString.length() == 0) { return getMembers(g, firstResult, maxResults); - - SearchResults results = SearchResults.instance(); + } String sString = "%" + searchString + "%"; - String queryString = "select m.user as u from VOMSMapping m join m.user.certificates as cert where " - + "m.group = :group and m.role is null and " - + "(cert.subjectString like :searchString " - + "or cert.ca.subjectString like :searchString " - + "or m.user.name like :searchString " - + "or m.user.surname like :searchString " - + "or m.user.emailAddress like :searchString " - + "or m.user.institution like :searchString)"; - - // String queryString = - // "select m.user as user from - // org.glite.security.voms.admin.persistence.model.VOMSMapping m where - // m.group = :group and m.role is null "+ - // "and (m.user.dn like :searchString or m.user.ca.subjectString like - // :searchString) order by m.user.dn asc"; - - Query q = HibernateFactory.getSession() - .createQuery(queryString) - .setString("searchString", sString); - + String commonQuery = "from VOMSMapping m join m.user.certificates as cert where " + + "m.group = :group and m.role is null and " + "(cert.subjectString like :searchString " + + "or cert.ca.subjectString like :searchString )"; + + String query = String.format("select distinct m.user as u %s", commonQuery); + String countQuery = String.format("select count(distinct m.user ) %s", commonQuery); + + Query q = + HibernateFactory.getSession().createQuery(query).setString("searchString", sString); + + Query count = + HibernateFactory.getSession().createQuery(countQuery).setString("searchString", sString); + q.setEntity("group", g); + count.setEntity("group", g); + + return paginatedFind(q, count, searchString, firstResult, maxResults); - q.setFirstResult(firstResult); - q.setMaxResults(maxResults); + } - List res = q.list(); + public SearchResults searchMembers(VOMSGroup g, String searchString, int firstResult, + int maxResults) { - results.setSearchString(searchString); - results.setResults(res); - results.setCount(countMatchingMembers(g, searchString)); - results.setFirstResult(firstResult); - results.setResultsPerPage(maxResults); + if (g == null) + throw new NullArgumentException("Cannot search members in a null group!"); - return results; + if (searchString == null || searchString.equals("") || searchString.length() == 0) { + return getMembers(g, firstResult, maxResults); + } + + String sString = "%" + searchString + "%"; + + String commonString = "from VOMSMapping m join m.user.certificates as cert" + + " where m.group = :group and m.role is null and" + + " (cert.subjectString like :searchString " + + "or cert.ca.subjectString like :searchString " + "or m.user.name like :searchString " + + "or m.user.surname like :searchString " + "or m.user.emailAddress like :searchString " + + "or m.user.institution like :searchString)"; + + Query q = HibernateFactory.getSession() + .createQuery(String.format("select distinct m.user as user %s", commonString)) + .setString("searchString", sString); + + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct m.user) %s", commonString)) + .setString("searchString", sString); + q.setEntity("group", g); + + count.setEntity("group", g); + + return paginatedFind(q, count, searchString, firstResult, maxResults); } public VOMSGroup findByName(String name) { @@ -282,10 +271,10 @@ public VOMSGroup findByName(String name) { if (!PathNamingScheme.isGroup(name)) throw new VOMSSyntaxException("Syntax error in group name: " + name); - String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup as g where g.name =:groupName"; + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSGroup as g where g.name =:groupName"; - Query q = HibernateFactory.getSession() - .createQuery(query); + Query q = HibernateFactory.getSession().createQuery(query); q.setString("groupName", name); @@ -296,8 +285,7 @@ public VOMSGroup findByName(String name) { public VOMSGroup findById(Long id) { - VOMSGroup g = (VOMSGroup) HibernateFactory.getSession() - .get(VOMSGroup.class, id); + VOMSGroup g = (VOMSGroup) HibernateFactory.getSession().get(VOMSGroup.class, id); return g; @@ -311,7 +299,7 @@ public VOMSGroup getVOGroup() { if (voName == null) throw new VOMSConfigurationException( - VOMSConfigurationConstants.VO_NAME + "undefined in configuration!"); + VOMSConfigurationConstants.VO_NAME + "undefined in configuration!"); VOMSGroup g = findByName("/" + voName); @@ -322,9 +310,9 @@ public VOMSGroup getVOGroup() { @SuppressWarnings("unchecked") public List getChildren(VOMSGroup parentGroup) { - String query = "from org.glite.security.voms.admin.persistence.model.VOMSGroup g where g.parent = :parentGroup and g != :parentGroup order by g.name"; - Query q = HibernateFactory.getSession() - .createQuery(query); + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSGroup g where g.parent = :parentGroup and g != :parentGroup order by g.name"; + Query q = HibernateFactory.getSession().createQuery(query); q.setEntity("parentGroup", parentGroup); @@ -337,15 +325,13 @@ public VOMSGroup create(String groupName) { return create(groupName, null, null); } - public VOMSGroup create(String groupName, String description, - Boolean isRestricted) { + public VOMSGroup create(String groupName, String description, Boolean isRestricted) { if (!PathNamingScheme.isGroup(groupName)) throw new VOMSSyntaxException("Syntax error in group name: " + groupName); if (findByName(groupName) != null) - throw new AlreadyExistsException( - "Group \"" + groupName + "\" already defined!"); + throw new AlreadyExistsException("Group \"" + groupName + "\" already defined!"); String[] parentGroupChain = PathNamingScheme.getParentGroupChain(groupName); String rootGroupName = getVOGroup().getName(); @@ -353,8 +339,7 @@ public VOMSGroup create(String groupName, String description, // the VO if (!parentGroupChain[0].equals(rootGroupName)) throw new IllegalArgumentException("The root group for \"" + groupName - + "\" must match the root group of the VO (i.e., " + rootGroupName - + ")"); + + "\" must match the root group of the VO (i.e., " + rootGroupName + ")"); String parentGroupName = PathNamingScheme.getParentGroupName(groupName); @@ -362,7 +347,7 @@ public VOMSGroup create(String groupName, String description, if (parentGroup == null) throw new NoSuchGroupException( - "Parent group \"" + parentGroupName + "\" not defined in database!"); + "Parent group \"" + parentGroupName + "\" not defined in database!"); VOMSGroup newGroup = new VOMSGroup(); newGroup.setName(groupName); @@ -376,8 +361,7 @@ public VOMSGroup create(String groupName, String description, log.debug("Creating group \"" + newGroup + "\"."); - HibernateFactory.getSession() - .save(newGroup); + HibernateFactory.getSession().save(newGroup); return newGroup; } @@ -386,15 +370,13 @@ public void delete(Long id) { VOMSGroup g = (VOMSGroup) findById(id); if (g == null) - throw new NoSuchGroupException( - "Group with id \"" + id + "\" not defined!"); + throw new NoSuchGroupException("Group with id \"" + id + "\" not defined!"); try { delete(g); } catch (ObjectNotFoundException e) { - throw new NoSuchGroupException( - "Group with id \"" + id + "\" not defined!"); + throw new NoSuchGroupException("Group with id \"" + id + "\" not defined!"); } } @@ -402,12 +384,9 @@ public void delete(Long id) { private void uncheckedDelete(VOMSGroup g) { if (!g.isRootGroup()) { - g.getMappings() - .clear(); - g.getAttributes() - .clear(); - HibernateFactory.getSession() - .delete(g); + g.getMappings().clear(); + g.getAttributes().clear(); + HibernateFactory.getSession().delete(g); } } @@ -423,12 +402,11 @@ public void deleteAll() { public void delete(VOMSGroup g) { if (!PathNamingScheme.isGroup(g.getName())) - throw new VOMSSyntaxException( - "Syntax error in group name for group: " + g); + throw new VOMSSyntaxException("Syntax error in group name for group: " + g); if (g.isRootGroup() && g.equals(getVOGroup())) throw new IllegalOperationException( - "VO root group \"" + g.getName() + "\" cannot be deleted!"); + "VO root group \"" + g.getName() + "\" cannot be deleted!"); if (findByName(g.getName()) == null) throw new NoSuchGroupException("Group \"" + g + "\" not defined!"); @@ -437,18 +415,15 @@ public void delete(VOMSGroup g) { if (!children.isEmpty()) throw new IllegalOperationException("The group \"" + g - + "\" cannot be deleted since it contains subgroups. Delete subgroups first."); + + "\" cannot be deleted since it contains subgroups. Delete subgroups first."); log.debug("Deleting group " + g + "\"."); - VOMSRoleDAO.instance() - .removeRoleAttributesForGroup(g); + VOMSRoleDAO.instance().removeRoleAttributesForGroup(g); - g.getMappings() - .clear(); + g.getMappings().clear(); - g.getAcls() - .clear(); + g.getAcls().clear(); // Delete admins and ACL permissions that are related to this group VOMSAdminDAO adminDAO = VOMSAdminDAO.instance(); @@ -456,15 +431,12 @@ public void delete(VOMSGroup g) { if (groupAdmin != null) { - ACLDAO.instance() - .deletePermissionsForAdmin(groupAdmin); + ACLDAO.instance().deletePermissionsForAdmin(groupAdmin); adminDAO.delete(groupAdmin); } - HibernateFactory.getSession() - .delete(g); - HibernateFactory.getSession() - .flush(); + HibernateFactory.getSession().delete(g); + HibernateFactory.getSession().flush(); } @@ -476,13 +448,12 @@ public VOMSGroup createVOGroup() { if (voName == null) throw new VOMSConfigurationException( - VOMSConfigurationConstants.VO_NAME + " undefined in configuration!"); + VOMSConfigurationConstants.VO_NAME + " undefined in configuration!"); VOMSGroup g = findByName("/" + voName); if (g != null) - throw new VOMSDatabaseException( - "Root group already defined for vo " + voName); + throw new VOMSDatabaseException("Root group already defined for vo " + voName); g = new VOMSGroup(); g.setName("/" + voName); @@ -493,14 +464,12 @@ public VOMSGroup createVOGroup() { // The ugly transaction management code here is acceptable since // the creation of the VO GROUP is performed only once during the // lifetime of a VO. - HibernateFactory.getSession() - .save(g); + HibernateFactory.getSession().save(g); HibernateFactory.commitTransaction(); HibernateFactory.beginTransaction(); g.setParent(g); - HibernateFactory.getSession() - .update(g); + HibernateFactory.getSession().update(g); HibernateFactory.commitTransaction(); } catch (HibernateException e) { @@ -515,15 +484,13 @@ public VOMSGroup createVOGroup() { } - public VOMSGroupAttribute setAttribute(VOMSGroup g, String attrName, - String attrValue) { + public VOMSGroupAttribute setAttribute(VOMSGroup g, String attrName, String attrValue) { - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); if (desc == null) - throw new NoSuchAttributeException( - "Attribute '" + attrName + "' is not defined in this vo."); + throw new NoSuchAttributeException("Attribute '" + attrName + "' is not defined in this vo."); VOMSGroupAttribute val = g.getAttributeByName(attrName); @@ -535,28 +502,26 @@ public VOMSGroupAttribute setAttribute(VOMSGroup g, String attrName, g.addAttribute(val); } - HibernateFactory.getSession() - .update(g); + HibernateFactory.getSession().update(g); return val; } - public VOMSGroupAttribute createAttribute(VOMSGroup g, String attrName, - String attrDesc, String attrValue) { + public VOMSGroupAttribute createAttribute(VOMSGroup g, String attrName, String attrDesc, + String attrValue) { if (g.getAttributeByName(attrName) != null) - throw new AlreadyExistsException("Attribute \"" + attrName - + "\" already defined for group \"" + g + "\"."); + throw new AlreadyExistsException( + "Attribute \"" + attrName + "\" already defined for group \"" + g + "\"."); - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); if (desc == null) - desc = VOMSAttributeDAO.instance() - .createAttributeDescription(attrName, attrDesc); - log.debug("Creating attribute \"(" + attrName + "," + attrValue - + ")\" for group \"" + g + "\""); + desc = VOMSAttributeDAO.instance().createAttributeDescription(attrName, attrDesc); + log + .debug("Creating attribute \"(" + attrName + "," + attrValue + ")\" for group \"" + g + "\""); VOMSGroupAttribute val = VOMSGroupAttribute.instance(desc, attrValue, g); g.addAttribute(val); @@ -569,8 +534,8 @@ public VOMSGroupAttribute deleteAttribute(VOMSGroup g, String attrName) { VOMSGroupAttribute ga = g.getAttributeByName(attrName); if (ga == null) - throw new NoSuchAttributeException("Attribute named '" + attrName - + "' not defined for group '" + g.getName() + "'!"); + throw new NoSuchAttributeException( + "Attribute named '" + attrName + "' not defined for group '" + g.getName() + "'!"); deleteAttribute(g, ga); @@ -580,8 +545,7 @@ public VOMSGroupAttribute deleteAttribute(VOMSGroup g, String attrName) { public void deleteAttribute(VOMSGroup g, VOMSGroupAttribute val) { - log.debug( - "Deleting attribute \"" + val.getName() + "\" from group \"" + g + "\""); + log.debug("Deleting attribute \"" + val.getName() + "\" from group \"" + g + "\""); g.deleteAttribute(val); @@ -604,10 +568,7 @@ public List getMembers(VOMSGroup g) { throw new NullArgumentException("Cannot get members of a null group!"); String query = "select m.user from VOMSMapping m where m.group = :group and m.role is null"; - return HibernateFactory.getSession() - .createQuery(query) - .setEntity("group", g) - .list(); + return HibernateFactory.getSession().createQuery(query).setEntity("group", g).list(); } @@ -617,11 +578,9 @@ public List getMemberSubjectStrings(VOMSGroup g) { if (g == null) throw new NullArgumentException("Cannot get members of a null group!"); - String query = "select distinct c.subjectString from VOMSUser u join u.certificates c join u.mappings m where u.suspended is false and c.suspended is false and m.group = :group and m.role is null"; + String query = + "select distinct c.subjectString from VOMSUser u join u.certificates c join u.mappings m where u.suspended is false and c.suspended is false and m.group = :group and m.role is null"; - return HibernateFactory.getSession() - .createQuery(query) - .setEntity("group", g) - .list(); + return HibernateFactory.getSession().createQuery(query).setEntity("group", g).list(); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSRoleDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSRoleDAO.java index 2d49c069..8dff1cd3 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSRoleDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSRoleDAO.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.persistence.dao; +import static org.glite.security.voms.admin.persistence.dao.SearchUtils.paginatedFind; + import java.util.Iterator; import java.util.List; @@ -55,8 +57,7 @@ public int countRoles() { String query = "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSRole"; - Long count = (Long) HibernateFactory.getSession().createQuery(query) - .uniqueResult(); + Long count = (Long) HibernateFactory.getSession().createQuery(query).uniqueResult(); return count.intValue(); } @@ -64,10 +65,13 @@ public int countRoles() { public int countMatches(String searchString) { String sString = "%" + searchString + "%"; - String query = "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSRole where name like :searchString"; + String query = + "select count(*) from org.glite.security.voms.admin.persistence.model.VOMSRole where name like :searchString"; - Long count = (Long) HibernateFactory.getSession().createQuery(query) - .setString("searchString", sString).uniqueResult(); + Long count = (Long) HibernateFactory.getSession() + .createQuery(query) + .setString("searchString", sString) + .uniqueResult(); return count.intValue(); } @@ -92,20 +96,18 @@ public SearchResults getAll(int firstResult, int maxResults) { } - public SearchResults search(String searchString, int firstResult, - int maxResults) { + public SearchResults search(String searchString, int firstResult, int maxResults) { - if (searchString == null || searchString.equals("") - || searchString.length() == 0) + if (searchString == null || searchString.equals("") || searchString.length() == 0) return getAll(firstResult, maxResults); SearchResults results = SearchResults.instance(); String sString = "%" + searchString + "%"; - String query = "from org.glite.security.voms.admin.persistence.model.VOMSRole where name like :searchString"; + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSRole where name like :searchString"; - Query q = HibernateFactory.getSession().createQuery(query) - .setString("searchString", sString); + Query q = HibernateFactory.getSession().createQuery(query).setString("searchString", sString); q.setFirstResult(firstResult); q.setMaxResults(maxResults); @@ -121,8 +123,8 @@ public SearchResults search(String searchString, int firstResult, return results; } - public SearchResults searchMembers(VOMSGroup g, VOMSRole r, - String searchString, int firstResult, int maxResults) { + public SearchResults searchMemberBySubject(VOMSGroup g, VOMSRole r, String searchString, + int firstResult, int maxResults) { if (g == null) throw new NullArgumentException("Cannot search members in a null group!"); @@ -130,38 +132,35 @@ public SearchResults searchMembers(VOMSGroup g, VOMSRole r, if (r == null) throw new NullArgumentException("Cannot search members in a null role!"); - if (searchString == null || searchString.equals("") - || searchString.length() == 0) + if (searchString == null || searchString.equals("") || searchString.length() == 0) return getMembers(g, r, firstResult, maxResults); - SearchResults results = SearchResults.instance(); String sString = "%" + searchString + "%"; - String queryString = "select m.user as user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role is :role " - + "and m.user.dn like :searchString order by m.user.dn asc"; + String commonString = + "from VOMSUser u join u.certificates c join u.mappings m where m.group = :group and m.role = :role and" + + "(c.subjectString like :searchString or c.ca.subjectString like :searchString)"; - Query q = HibernateFactory.getSession().createQuery(queryString) + Query q = HibernateFactory.getSession() + .createQuery(String.format("select distinct u %s", commonString)) + .setString("searchString", sString); + + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct u) %s", commonString)) .setString("searchString", sString); q.setEntity("group", g); q.setEntity("role", r); - q.setFirstResult(firstResult); - q.setMaxResults(maxResults); - - List res = q.list(); - - results.setSearchString(searchString); - results.setResults(res); - results.setCount(countMatchingMembers(g, r, searchString)); - results.setFirstResult(firstResult); - results.setResultsPerPage(maxResults); - return results; + count.setEntity("group", g); + count.setEntity("role", r); + return paginatedFind(q, count, searchString, firstResult, maxResults); } - private int countMatchingMembers(VOMSGroup g, VOMSRole r, String searchString) { + public SearchResults searchMembers(VOMSGroup g, VOMSRole r, String searchString, int firstResult, + int maxResults) { if (g == null) throw new NullArgumentException("Cannot search members in a null group!"); @@ -169,27 +168,37 @@ private int countMatchingMembers(VOMSGroup g, VOMSRole r, String searchString) { if (r == null) throw new NullArgumentException("Cannot search members in a null role!"); - String sString; + if (searchString == null || searchString.equals("") || searchString.length() == 0) + return getMembers(g, r, firstResult, maxResults); - if (searchString == null) - sString = "%"; - else - sString = "%" + searchString + "%"; + String sString = "%" + searchString + "%"; - String queryString = "select count(m.user) from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role is :role " - + "and m.user.dn like :searchString order by m.user.dn asc"; + String commonString = "from VOMSMapping m join m.user.certificates as cert" + + " where m.group = :group and m.role is :role and" + + " (cert.subjectString like :searchString " + + "or cert.ca.subjectString like :searchString " + "or m.user.name like :searchString " + + "or m.user.surname like :searchString " + "or m.user.emailAddress like :searchString " + + "or m.user.institution like :searchString)"; + + Query q = HibernateFactory.getSession() + .createQuery(String.format("select distinct m.user as user %s", commonString)) + .setString("searchString", sString); - Query q = HibernateFactory.getSession().createQuery(queryString); + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct m.user) %s", commonString)) + .setString("searchString", sString); - q.setString("searchString", sString); q.setEntity("group", g); q.setEntity("role", r); - return ((Long) q.uniqueResult()).intValue(); + count.setEntity("group", g); + count.setEntity("role", r); + + return paginatedFind(q, count, searchString, firstResult, maxResults); + } - private SearchResults getMembers(VOMSGroup g, VOMSRole r, int firstResult, - int maxResults) { + private SearchResults getMembers(VOMSGroup g, VOMSRole r, int firstResult, int maxResults) { if (g == null) throw new NullArgumentException("Cannot search members in a null group!"); @@ -197,30 +206,19 @@ private SearchResults getMembers(VOMSGroup g, VOMSRole r, int firstResult, if (r == null) throw new NullArgumentException("Cannot search members in a null role!"); - int membersCount = r.getUsers(g).size(); - - SearchResults results = SearchResults.instance(); - - String queryString = "select m.user as user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role is :role " - + "order by m.user.dn asc"; + String commonQuery = "from VOMSMapping m where m.group = :group and m.role is :role "; - Query q = HibernateFactory.getSession().createQuery(queryString); + Query q = HibernateFactory.getSession() + .createQuery(String.format("select m.user as user %s", commonQuery)); + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct m.user ) %s", commonQuery)); q.setEntity("group", g); q.setEntity("role", r); + count.setEntity("group", g); + count.setEntity("role", r); - q.setFirstResult(firstResult); - q.setMaxResults(maxResults); - - List res = q.list(); - - results.setSearchString(null); - results.setResults(res); - results.setCount(membersCount); - results.setFirstResult(firstResult); - results.setResultsPerPage(maxResults); - - return results; + return SearchUtils.paginatedFind(q, count, null, firstResult, maxResults); } @@ -233,10 +231,13 @@ public List getAllNames() { public VOMSRole findByName(String roleName) { - String query = "from org.glite.security.voms.admin.persistence.model.VOMSRole where name = :name"; + String query = + "from org.glite.security.voms.admin.persistence.model.VOMSRole where name = :name"; - return (VOMSRole) HibernateFactory.getSession().createQuery(query) - .setString("name", roleName).uniqueResult(); + return (VOMSRole) HibernateFactory.getSession() + .createQuery(query) + .setString("name", roleName) + .uniqueResult(); } public VOMSRole findById(Long id) { @@ -247,8 +248,7 @@ public VOMSRole findById(Long id) { public VOMSRole create(String roleName) { if (findByName(roleName) != null) - throw new AlreadyExistsException("Role \"" + roleName - + "\" already defined in database!"); + throw new AlreadyExistsException("Role \"" + roleName + "\" already defined in database!"); VOMSRole r = new VOMSRole(roleName); @@ -260,10 +260,8 @@ public VOMSRole create(String roleName) { public void deleteAll() { - HibernateFactory - .getSession() - .createQuery( - "delete from org.glite.security.voms.admin.persistence.model.VOMSRole") + HibernateFactory.getSession() + .createQuery("delete from org.glite.security.voms.admin.persistence.model.VOMSRole") .executeUpdate(); } @@ -273,8 +271,7 @@ public VOMSRole delete(Long id) { VOMSRole r = findById(id); if (r == null) - throw new NoSuchRoleException("Role with id \"" + id - + "\" is not defined in database!"); + throw new NoSuchRoleException("Role with id \"" + id + "\" is not defined in database!"); delete(r); return r; @@ -284,8 +281,7 @@ public VOMSRole delete(String roleName) { VOMSRole r = findByName(roleName); if (r == null) - throw new NoSuchRoleException("Role '" + roleName - + "' is not defined in database!"); + throw new NoSuchRoleException("Role '" + roleName + "' is not defined in database!"); delete(r); @@ -296,8 +292,7 @@ public VOMSRole delete(String roleName) { public VOMSRole delete(VOMSRole r) { if (findByName(r.getName()) == null) - throw new NoSuchRoleException("Role \"" + r - + "\" is not defined in database!"); + throw new NoSuchRoleException("Role \"" + r + "\" is not defined in database!"); r.getMappings().clear(); @@ -327,20 +322,18 @@ public void removeRoleAttributesForGroup(VOMSGroup g) { String deleteString = "delete from VOMSRoleAttribute where group = :group"; - HibernateFactory.getSession().createQuery(deleteString) - .setEntity("group", g).executeUpdate(); + HibernateFactory.getSession().createQuery(deleteString).setEntity("group", g).executeUpdate(); } - public VOMSRoleAttribute setAttribute(VOMSRole r, VOMSGroup g, - String attrName, String attrValue) { + public VOMSRoleAttribute setAttribute(VOMSRole r, VOMSGroup g, String attrName, + String attrValue) { - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); if (desc == null) - throw new NoSuchAttributeException("Attribute '" + attrName - + "' is not defined in this vo."); + throw new NoSuchAttributeException("Attribute '" + attrName + "' is not defined in this vo."); VOMSRoleAttribute val = r.getAttributeByName(g, attrName); @@ -356,19 +349,18 @@ public VOMSRoleAttribute setAttribute(VOMSRole r, VOMSGroup g, } - public VOMSRoleAttribute createAttribute(VOMSRole r, VOMSGroup g, - String attrName, String attrDesc, String attrValue) { + public VOMSRoleAttribute createAttribute(VOMSRole r, VOMSGroup g, String attrName, + String attrDesc, String attrValue) { if (r.getAttributeByName(g, attrName) != null) - throw new AlreadyExistsException("Attribute \"" + attrName - + "\" already defined for role \"" + r + "\" in group \"" + g + "\"."); + throw new AlreadyExistsException("Attribute \"" + attrName + "\" already defined for role \"" + + r + "\" in group \"" + g + "\"."); - VOMSAttributeDescription desc = VOMSAttributeDAO.instance() - .getAttributeDescriptionByName(attrName); + VOMSAttributeDescription desc = + VOMSAttributeDAO.instance().getAttributeDescriptionByName(attrName); if (desc == null) - desc = VOMSAttributeDAO.instance().createAttributeDescription(attrName, - attrDesc); + desc = VOMSAttributeDAO.instance().createAttributeDescription(attrName, attrDesc); VOMSRoleAttribute val = VOMSRoleAttribute.instance(desc, attrValue, g, r); @@ -383,11 +375,11 @@ public VOMSRoleAttribute deleteAttributeByName(VOMSRole r, VOMSGroup g, String a VOMSRoleAttribute attr = r.getAttributeByName(g, attrName); if (attr == null) - throw new NoSuchAttributeException("Attribute '" + attrName - + "' not defined for role '" + r.getName() + "' in group '" + g + "'."); + throw new NoSuchAttributeException("Attribute '" + attrName + "' not defined for role '" + + r.getName() + "' in group '" + g + "'."); deleteAttribute(r, attr); - + return attr; } @@ -407,9 +399,13 @@ public List getMembers(VOMSGroup g, VOMSRole r) { if (r == null) throw new IllegalArgumentException("role parameter must be non-null!"); - String query = "select m.user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role = :role"; - return HibernateFactory.getSession().createQuery(query) - .setEntity("group", g).setEntity("role", r).list(); + String query = + "select m.user from org.glite.security.voms.admin.persistence.model.VOMSMapping m where m.group = :group and m.role = :role"; + return HibernateFactory.getSession() + .createQuery(query) + .setEntity("group", g) + .setEntity("role", r) + .list(); } @@ -426,9 +422,13 @@ public Object getMemberSubjectStrings(VOMSGroup g, VOMSRole r) { if (r == null) throw new IllegalArgumentException("role parameter must be non-null!"); - String query = "select distinct c.subjectString from VOMSUser u join u.certificates c join u.mappings m where u.suspended is false and c.suspended is false and m.group = :group and m.role = :role"; + String query = + "select distinct c.subjectString from VOMSUser u join u.certificates c join u.mappings m where u.suspended is false and c.suspended is false and m.group = :group and m.role = :role"; - return HibernateFactory.getSession().createQuery(query) - .setEntity("group", g).setEntity("role", r).list(); + return HibernateFactory.getSession() + .createQuery(query) + .setEntity("group", g) + .setEntity("role", r) + .list(); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index dc49e2d6..98ce93d7 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.persistence.dao; +import static org.glite.security.voms.admin.persistence.dao.SearchUtils.paginatedFind; + import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Calendar; @@ -255,9 +257,10 @@ public List findAUPFailingUsers(AUP aup) { // Add users that have a valid aup acceptance record that needs to be // checked against // the reacceptance period - Query q3 = HibernateFactory.getSession().createQuery( - "select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true" - + " and r.lastAcceptanceDate > :lastUpdateTime "); + Query q3 = HibernateFactory.getSession() + .createQuery( + "select u from VOMSUser u join u.aupAcceptanceRecords r where r.aupVersion.active = true" + + " and r.lastAcceptanceDate > :lastUpdateTime "); q3.setTimestamp("lastUpdateTime", aupLastUpdateTime); @@ -814,28 +817,6 @@ public List findAll() { return result; } - private SearchResults paginatedFind(Query q, Query countQuery, String searchString, - int firstResults, int maxResults) { - - SearchResults res = SearchResults.instance(); - - res.setSearchString(searchString); - - q.setFirstResult(firstResults); - q.setMaxResults(maxResults); - - res.setResults(q.list()); - - Long count = (Long) countQuery.uniqueResult(); - - res.setCount(count.intValue()); - - res.setFirstResult(firstResults); - res.setResultsPerPage(maxResults); - - return res; - } - private String getUserOrderClause() { // If endTime is ignored by configuration, we should not consider @@ -931,6 +912,32 @@ public Long countSuspendedUsers() { } + + @SuppressWarnings({"rawtypes", "deprecation"}) + public SearchResults searchBySubject(String searchString, int firstResults, int maxResults) { + + if (searchString == null || searchString.trim().equals("") || searchString.length() == 0) { + return findAll(firstResults, maxResults); + } + + String sString = "%" + searchString + "%"; + + String queryString = "from VOMSUser u join u.certificates as cert where" + + " cert.subjectString like:searchString or cert.ca.subjectString like :searchString " + + getUserOrderClause(); + + Query q = HibernateFactory.getSession() + .createQuery(String.format("select distinct u %s", queryString)); + + Query count = HibernateFactory.getSession() + .createQuery(String.format("select count(distinct u) %s", queryString)); + + q.setString("searchString", sString); + count.setString("searchString", sString); + + return paginatedFind(q, count, searchString, firstResults, maxResults); + } + public SearchResults searchExpired(String searchString, int firstResults, int maxResults) { log.debug("searchString:" + searchString + ",firstResults: " + firstResults + ",maxResults: " @@ -981,9 +988,9 @@ public SearchResults searchWithPendingAUPRequest(String searchString, int firstR if (searchStringEmpty(searchString)) { - Query q = - HibernateFactory.getSession().createQuery("select distinct u " + queryString).setEntity( - "aup", aup); + Query q = HibernateFactory.getSession() + .createQuery("select distinct u " + queryString) + .setEntity("aup", aup); String countQuery = String.format("select count(distinct u) %s", queryString); Query countQ = HibernateFactory.getSession().createQuery(countQuery).setEntity("aup", aup); @@ -1121,7 +1128,7 @@ public Long countExpiringUsers(Integer intervalInDays) { String query = "select count(distinct u) from VOMSUser u where u.endTime between :startDate AND :endDate " - + "and suspended is false order by u.endTime asc"; + + "and suspended is false order by u.endTime asc"; Calendar cal = Calendar.getInstance(); @@ -1129,9 +1136,8 @@ public Long countExpiringUsers(Integer intervalInDays) { cal.add(Calendar.DAY_OF_YEAR, intervalInDays); Date intervalDate = cal.getTime(); - - Query q = HibernateFactory.getSession() - .createQuery(query); + + Query q = HibernateFactory.getSession().createQuery(query); q.setDate("startDate", now); q.setDate("endDate", intervalDate); @@ -1140,7 +1146,7 @@ public Long countExpiringUsers(Integer intervalInDays) { @SuppressWarnings("unchecked") public List findExpiringUsers(Integer intervalInDays) { - + Calendar cal = Calendar.getInstance(); Date now = cal.getTime(); @@ -1150,11 +1156,10 @@ public List findExpiringUsers(Integer intervalInDays) { String query = "select distinct u from VOMSUser u where u.endTime between :startDate AND :endDate " - + "and suspended is false order by u.endTime asc"; + + "and suspended is false order by u.endTime asc"; + + Query q = HibernateFactory.getSession().createQuery(query); - Query q = HibernateFactory.getSession() - .createQuery(query); - q.setDate("startDate", now); q.setDate("endDate", intervalDate); @@ -1163,8 +1168,9 @@ public List findExpiringUsers(Integer intervalInDays) { public VOMSUser lookup(String certificateSubject, String certificateIssuer) { - return LookupPolicyProvider.instance().lookupStrategy().lookup(this, certificateSubject, - certificateIssuer); + return LookupPolicyProvider.instance() + .lookupStrategy() + .lookup(this, certificateSubject, certificateIssuer); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UserInfoAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UserInfoAction.java index d5ed6b29..94af5419 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UserInfoAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UserInfoAction.java @@ -29,7 +29,7 @@ import com.opensymphony.xwork2.Preparable; @ParentPackage("json") -@Results({@Result(name = BaseAction.SUCCESS, type = "json", params={"root", "userInfo"}), +@Results({@Result(name = BaseAction.SUCCESS, type = "json", params={"root", "userInfo","excludeNullProperties", "true"}), @Result(name=UserInfoAction.NOT_FOUND, type="httpheader", params={"error", "404", "errorMessage", "User not found"}) }) public class UserInfoAction extends BaseAction implements Preparable { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UsersAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UsersAction.java index 34ac2e86..f66362c8 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UsersAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/UsersAction.java @@ -31,7 +31,7 @@ import com.opensymphony.xwork2.Preparable; @ParentPackage("json") -@Results({@Result(name = BaseAction.SUCCESS, type = "json", params={"root", "result"})}) +@Results({@Result(name = BaseAction.SUCCESS, type = "json", params={"root", "result", "excludeNullProperties", "true"})}) public class UsersAction extends BaseAction implements Preparable{ /** diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/group/groupDetail.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/group/groupDetail.jsp index a93d5f65..d4724601 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/group/groupDetail.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/group/groupDetail.jsp @@ -16,45 +16,23 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - - - + + + - - - +

- Group - - - View ACL + Group + + + + + View ACL

- - - - - + + +
@@ -62,9 +40,7 @@
- +
@@ -72,21 +48,21 @@
- +
- -

Group managers:

    -
  • -
  • +
  • + + - + +
@@ -95,69 +71,30 @@

Membership information

- +
- - - - - + + + + +
-
- - + +
-

Attributes information

- - + -
- - - - - - + + - - - - - - diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/group/searchMember.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/group/searchMember.jsp index 14f40e80..c0773479 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/group/searchMember.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/group/searchMember.jsp @@ -38,7 +38,7 @@ matches found for '': -
+
@@ -55,94 +55,25 @@ User information - Certificates - - - - -
- - -
- -
-
- -
- No name specified for this user. -
-
- -
- -
-
- -
- No institution specified for this user. -
-
- - - - -
- This user is suspended. -
Reason: - -
- -
-
- - - - -
- Certificates listed below are suspended due to membership suspension: -
-
-
    - - -
  1. - - -
    suspended-cert"> - - -
    -
    suspended-cert"> - - -
    -
  2. -
    -
- - - - - - - - - more info - - - - -
- + + + + + + + + + + more info + + + +
@@ -152,8 +83,7 @@ - + linkStyleClass="navBarLink" id="searchResults" searchPanelId="mmResults"/>
diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/role/searchMember.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/role/searchMember.jsp index b7141493..0efa023c 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/role/searchMember.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/role/searchMember.jsp @@ -15,150 +15,63 @@ limitations under the License. --%> -<%@include - file="/WEB-INF/p/shared/taglibs.jsp"%> - -
- +<%@include file="/WEB-INF/p/shared/taglibs.jsp"%> +
- - No members found having role ' in group ''. + + No members found having role ' in group ''. - - No matches found for ''. + + No matches found for ''. -
- matches found for '': -
+
+ + match + es + found for ' + + ': +
- - - - - - - - - - - -
- - - - - -
User informationCertificates + + + + + + + + + + + + + - - - - - - - - - - - - - -
+ + + + + + + more info + +
-
- - -
- -
-
- -
- No name specified for this user. -
-
- -
- -
-
- -
- No institution specified for this user. -
-
- - - - -
- This user is suspended. -
Reason: - -
- -
-
-
- -
- Certificates listed below are suspended due to membership suspension: -
-
-
    - - -
  1. - - -
    suspended-cert"> - - -
    -
    suspended-cert"> - - -
    -
  2. -
    -
-
- - - - - - more info - - -
-
- - - - - - - - - - -
+ +
+
+ + + + + + + +
-
+
\ No newline at end of file diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp index dd8898ea..356b6554 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp @@ -17,6 +17,8 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> + +
@@ -53,12 +55,13 @@ var="thisCertCA" />${thisCertCA}
-
Added on: - - -
- + +
Added on: + + +
+
diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp index 20c10ec2..aef83f70 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp @@ -17,7 +17,9 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - + + + diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/suspensionDetail.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/suspensionDetail.jsp index 3f3ac15e..9e766a12 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/suspensionDetail.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/suspensionDetail.jsp @@ -24,9 +24,8 @@
- Suspended - + Suspended
diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp index 6f483c79..fd2769e2 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp @@ -16,175 +16,103 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - - - - + + +
- -
- - ( ${id} ) - - - + + +
+ + ( ${id} ) + + + + + +
+
+ + - -
-
- -
- +
+
+ + User + - - User - - + User - -
-
- - - - - - - + + + + + + - - - - - + + + + - - - + - + - + - - + - - - + - - + - - + - + - - - + - +
- - - + - + - - + - - - + - - + - - diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp index e2e2599c..264335a3 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp @@ -16,54 +16,48 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - -
- -
- -
-
- -
No name specified for this user.
-
- -
- + + +
+ +
+ +
+
+ +
+ User + +
+
+ +
+ +
+
+ - - -
No institution specified for this user.
-
- - - - - -
- -
Certificates:
+
Certificates:
+
+ +
+ User +
+
    - - +
  1. suspended-cert"> - + ${thisCertDN}
    suspended-cert"> - + ${thisCertCA}
  2. diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/users.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/users.jsp index 13a23d28..de050aab 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/users.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/users.jsp @@ -16,188 +16,104 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - - - - - - - + + +

    Users:

    -
    - - - - - Limit to: - - Suspended - - - + + + + + Limit to: + + Suspended + + - Pending sign AUP - request + Pending sign AUP request - - + + - Show: -
    - -
    - + No users found. - No users found matching search string ''. + No users found matching search string ''. -
- - + + + - +
- - + + + + + - - + + - - +
-
- User information
- - + -
- - - +
+ + - + more info
@@ -206,11 +122,7 @@
- - - +
diff --git a/voms-admin-server/src/main/webapp/style/style.css b/voms-admin-server/src/main/webapp/style/style.css index 74c6c312..2ec603d9 100644 --- a/voms-admin-server/src/main/webapp/style/style.css +++ b/voms-admin-server/src/main/webapp/style/style.css @@ -69,14 +69,14 @@ font-size: xx-small; display: block; float: right; - margin-bottom: .5ex; + margin-bottom: 1ex; } .resultsFooter { font-size: xx-small; display: block; float: right; - margin-top: .5ex; + margin-top: 1ex; } .resultsCount { From e734c75c6cf496655a3ec1caa5b354667e272319 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 20 Dec 2019 17:44:14 +0100 Subject: [PATCH 37/63] Limit information shown to unauthenticated users And, when OrgDB integration is turned on, adjust the required fields configuration parameter as expected. --- docker-compose.yml | 2 +- docker/voms-admin-server/setup/orgdb-util.sh | 9 + .../configuration/VOMSConfiguration.java | 332 +++++++----------- .../VOMSConfigurationConstants.java | 7 + .../integration/cern/HrDbConfigurator.java | 10 +- .../integration/orgdb/OrgDBConfigurator.java | 4 + .../view/actions/register/StartAction.java | 13 + .../actions/register/SubmitRequestAction.java | 35 +- .../register/orgdb/SubmitRequestAction.java | 4 - .../admin/view/actions/user/HomeAction.java | 2 + .../user/SavePersonalInformationAction.java | 109 +++--- .../view/actions/user/UserActionSupport.java | 11 +- .../p/register/default/registration.jsp | 28 +- .../p/register/orgdb/registration2.jsp | 8 +- .../webapp/WEB-INF/p/user/certificates.jsp | 9 +- .../webapp/WEB-INF/p/user/personalInfo.jsp | 73 ++-- .../webapp/WEB-INF/p/user/requestHistory.jsp | 2 +- .../main/webapp/WEB-INF/p/user/userDetail.jsp | 2 +- .../main/webapp/WEB-INF/p/user/userInfo.jsp | 7 +- 19 files changed, 331 insertions(+), 336 deletions(-) create mode 100644 docker/voms-admin-server/setup/orgdb-util.sh diff --git a/docker-compose.yml b/docker-compose.yml index ba1bea30..d1d5e468 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,7 +41,7 @@ services: - ~/git/voms-admin-server/docker/voms-admin-server/setup:/scripts:ro - ~/git/orgdb-fake-users/:/orgdb-fake-users:ro - ~/git/voms-migrate:/migrate:ro - # - ~/orgdb:/orgdb:ro + - ~/orgdb:/orgdb:ro ports: # 20001 is the default yourkit port diff --git a/docker/voms-admin-server/setup/orgdb-util.sh b/docker/voms-admin-server/setup/orgdb-util.sh new file mode 100644 index 00000000..78346cf2 --- /dev/null +++ b/docker/voms-admin-server/setup/orgdb-util.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -ex + +source /etc/sysconfig/voms-admin + +OJDBC_JAR=${OJDBC_JAR:-${ORACLE_LIBRARY_PATH}/ojdbc6.jar} +ORACLE_ENV="LD_LIBRARY_PATH=$ORACLE_LIBRARY_PATH TNS_ADMIN=$TNS_ADMIN" + +TNS_ADMIN=/home/voms LD_LIBRARY_PATH=${ORACLE_LIBRARY_PATH} java -cp ${OJDBC_JAR}:'/var/lib/voms-admin/lib/*':/usr/share/java/voms-admin.jar org.glite.security.voms.admin.integration.orgdb.tools.OrgDBUtil -c /etc/voms-admin/test_0/orgdb.properties $@ diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java index ec26840c..f6c781d2 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfiguration.java @@ -16,6 +16,7 @@ package org.glite.security.voms.admin.configuration; import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.PERMISSION_CACHE_DISABLE; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.PI_REQUIRED_FIELDS; import static org.glite.security.voms.admin.util.SysconfigUtil.SYSCONFIG_CONF_DIR; import static org.glite.security.voms.admin.util.SysconfigUtil.SYSCONFIG_DEFAULT_FILE_PATH; @@ -34,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.Properties; +import java.util.Set; import javax.servlet.ServletContext; @@ -52,6 +54,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Splitter; +import com.google.common.collect.Sets; + import eu.emi.security.authn.x509.impl.PEMCredential; public class VOMSConfiguration { @@ -61,8 +66,7 @@ public class VOMSConfiguration { public synchronized static VOMSConfiguration load(ServletContext context) { if (instance != null) - throw new VOMSConfigurationException( - "VOMS configuration already loaded!"); + throw new VOMSConfigurationException("VOMS configuration already loaded!"); instance = new VOMSConfiguration(context); @@ -82,7 +86,7 @@ public static VOMSConfiguration instance() { if (instance == null) throw new VOMSConfigurationException( - "VOMS configuration not loaded! Use the load method to load it."); + "VOMS configuration not loaded! Use the load method to load it."); return instance; @@ -103,19 +107,16 @@ private void loadConfDir() { if (config.getString(SYSCONFIG_CONF_DIR) == null) { log.warn("{} undefined in VOMS Admin sysconfig.", SYSCONFIG_CONF_DIR); - log.warn("Setting default value assuming EMI packaging: {}", - "/etc/voms-admin"); + log.warn("Setting default value assuming EMI packaging: {}", "/etc/voms-admin"); config.setProperty(SYSCONFIG_CONF_DIR, "/etc/voms-admin"); } - if (context != null - && context.getInitParameter(SYSCONFIG_CONF_DIR) != null) { + if (context != null && context.getInitParameter(SYSCONFIG_CONF_DIR) != null) { log.info("Setting {} from context: {}", SYSCONFIG_CONF_DIR, - context.getInitParameter(SYSCONFIG_CONF_DIR)); - config.setProperty(SYSCONFIG_CONF_DIR, - context.getInitParameter(SYSCONFIG_CONF_DIR)); + context.getInitParameter(SYSCONFIG_CONF_DIR)); + config.setProperty(SYSCONFIG_CONF_DIR, context.getInitParameter(SYSCONFIG_CONF_DIR)); } } @@ -152,18 +153,18 @@ private void loadHostAndPort() { if (context != null) { config.setProperty(VOMSConfigurationConstants.VOMS_SERVICE_PORT, - context.getInitParameter("PORT")); + context.getInitParameter("PORT")); config.setProperty(VOMSConfigurationConstants.VOMS_SERVICE_HOSTNAME, - context.getInitParameter("HOST")); + context.getInitParameter("HOST")); } } /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#addProperty(java.lang. - * String, java.lang.Object) + * @see org.apache.commons.configuration.Configuration#addProperty(java.lang. String, + * java.lang.Object) */ public void addProperty(String arg0, Object arg1) { @@ -183,8 +184,7 @@ public void clear() { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#clearProperty(java.lang - * .String) + * @see org.apache.commons.configuration.Configuration#clearProperty(java.lang .String) */ public void clearProperty(String arg0) { @@ -194,8 +194,7 @@ public void clearProperty(String arg0) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#containsKey(java.lang. - * String) + * @see org.apache.commons.configuration.Configuration#containsKey(java.lang. String) */ public boolean containsKey(String arg0) { @@ -205,8 +204,7 @@ public boolean containsKey(String arg0) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getBigDecimal(java.lang - * .String) + * @see org.apache.commons.configuration.Configuration#getBigDecimal(java.lang .String) */ public BigDecimal getBigDecimal(String arg0) { @@ -216,8 +214,8 @@ public BigDecimal getBigDecimal(String arg0) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getBigDecimal(java.lang - * .String, java.math.BigDecimal) + * @see org.apache.commons.configuration.Configuration#getBigDecimal(java.lang .String, + * java.math.BigDecimal) */ public BigDecimal getBigDecimal(String arg0, BigDecimal arg1) { @@ -227,8 +225,7 @@ public BigDecimal getBigDecimal(String arg0, BigDecimal arg1) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getBigInteger(java.lang - * .String) + * @see org.apache.commons.configuration.Configuration#getBigInteger(java.lang .String) */ public BigInteger getBigInteger(String arg0) { @@ -238,8 +235,8 @@ public BigInteger getBigInteger(String arg0) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getBigInteger(java.lang - * .String, java.math.BigInteger) + * @see org.apache.commons.configuration.Configuration#getBigInteger(java.lang .String, + * java.math.BigInteger) */ public BigInteger getBigInteger(String arg0, BigInteger arg1) { @@ -249,9 +246,7 @@ public BigInteger getBigInteger(String arg0, BigInteger arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getBoolean(java.lang.String - * ) + * @see org.apache.commons.configuration.Configuration#getBoolean(java.lang.String ) */ public boolean getBoolean(String arg0) { @@ -261,9 +256,7 @@ public boolean getBoolean(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getBoolean(java.lang.String - * , boolean) + * @see org.apache.commons.configuration.Configuration#getBoolean(java.lang.String , boolean) */ public boolean getBoolean(String arg0, boolean arg1) { @@ -273,9 +266,8 @@ public boolean getBoolean(String arg0, boolean arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getBoolean(java.lang.String - * , java.lang.Boolean) + * @see org.apache.commons.configuration.Configuration#getBoolean(java.lang.String , + * java.lang.Boolean) */ public Boolean getBoolean(String arg0, Boolean arg1) { @@ -285,8 +277,7 @@ public Boolean getBoolean(String arg0, Boolean arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getByte(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getByte(java.lang.String) */ public byte getByte(String arg0) { @@ -296,9 +287,7 @@ public byte getByte(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getByte(java.lang.String, - * byte) + * @see org.apache.commons.configuration.Configuration#getByte(java.lang.String, byte) */ public byte getByte(String arg0, byte arg1) { @@ -308,9 +297,7 @@ public byte getByte(String arg0, byte arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getByte(java.lang.String, - * java.lang.Byte) + * @see org.apache.commons.configuration.Configuration#getByte(java.lang.String, java.lang.Byte) */ public Byte getByte(String arg0, Byte arg1) { @@ -344,8 +331,7 @@ private String getCustomizedContentPath() { public Properties getDatabaseProperties() { - String propFileName = getConfigurationDirectoryPath() - + "/database.properties"; + String propFileName = getConfigurationDirectoryPath() + "/database.properties"; Properties props = new Properties(); @@ -355,8 +341,7 @@ public Properties getDatabaseProperties() { } catch (IOException e) { log.error("Error loading database properties: " + e.getMessage(), e); - throw new VOMSException( - "Error loading database properties: " + e.getMessage(), e); + throw new VOMSException("Error loading database properties: " + e.getMessage(), e); } return props; @@ -365,15 +350,13 @@ public Properties getDatabaseProperties() { public String getDefaultVOAUPURL() { - return String.format("file://%s/vo-aup.txt", - getConfigurationDirectoryPath()); + return String.format("file://%s/vo-aup.txt", getConfigurationDirectoryPath()); } /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getDouble(java.lang.String ) + * @see org.apache.commons.configuration.Configuration#getDouble(java.lang.String ) */ public double getDouble(String arg0) { @@ -383,9 +366,7 @@ public double getDouble(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getDouble(java.lang.String , - * double) + * @see org.apache.commons.configuration.Configuration#getDouble(java.lang.String , double) */ public double getDouble(String arg0, double arg1) { @@ -395,8 +376,7 @@ public double getDouble(String arg0, double arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getDouble(java.lang.String , + * @see org.apache.commons.configuration.Configuration#getDouble(java.lang.String , * java.lang.Double) */ public Double getDouble(String arg0, Double arg1) { @@ -404,19 +384,16 @@ public Double getDouble(String arg0, Double arg1) { return config.getDouble(arg0, arg1); } - private InputStream getExternalLogbackConfiguration() - throws FileNotFoundException { + private InputStream getExternalLogbackConfiguration() throws FileNotFoundException { String path = getConfigurationDirectoryPath() + "/logback.runtime.xml"; File f = new File(path); if (!f.exists()) - log.warn( - "External logging configuration not found at path '" + path + "'... "); + log.warn("External logging configuration not found at path '" + path + "'... "); if (!f.canRead()) - log.warn( - "External logging configuration is not readable: '" + path + "'... "); + log.warn("External logging configuration is not readable: '" + path + "'... "); return new FileInputStream(f); @@ -425,8 +402,7 @@ private InputStream getExternalLogbackConfiguration() /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getFloat(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getFloat(java.lang.String) */ public float getFloat(String arg0) { @@ -436,9 +412,7 @@ public float getFloat(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getFloat(java.lang.String, - * float) + * @see org.apache.commons.configuration.Configuration#getFloat(java.lang.String, float) */ public float getFloat(String arg0, float arg1) { @@ -448,9 +422,7 @@ public float getFloat(String arg0, float arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getFloat(java.lang.String, - * java.lang.Float) + * @see org.apache.commons.configuration.Configuration#getFloat(java.lang.String, java.lang.Float) */ public Float getFloat(String arg0, Float arg1) { @@ -460,8 +432,7 @@ public Float getFloat(String arg0, Float arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getInt(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getInt(java.lang.String) */ public int getInt(String arg0) { @@ -471,9 +442,7 @@ public int getInt(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getInt(java.lang.String, - * int) + * @see org.apache.commons.configuration.Configuration#getInt(java.lang.String, int) */ public int getInt(String arg0, int arg1) { @@ -483,9 +452,8 @@ public int getInt(String arg0, int arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getInteger(java.lang.String - * , java.lang.Integer) + * @see org.apache.commons.configuration.Configuration#getInteger(java.lang.String , + * java.lang.Integer) */ public Integer getInteger(String arg0, Integer arg1) { @@ -505,8 +473,7 @@ public Iterator getKeys() { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getKeys(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getKeys(java.lang.String) */ public Iterator getKeys(String arg0) { @@ -516,8 +483,7 @@ public Iterator getKeys(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getList(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getList(java.lang.String) */ public List getList(String arg0) { @@ -527,9 +493,7 @@ public List getList(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getList(java.lang.String, - * java.util.List) + * @see org.apache.commons.configuration.Configuration#getList(java.lang.String, java.util.List) */ public List getList(String arg0, List arg1) { @@ -541,16 +505,14 @@ public List getLocallyConfiguredVOs() { String configDirPath = getString(SYSCONFIG_CONF_DIR); if (configDirPath == null) - throw new VOMSConfigurationException( - "No value found for " + SYSCONFIG_CONF_DIR + "!"); + throw new VOMSConfigurationException("No value found for " + SYSCONFIG_CONF_DIR + "!"); List voList = new ArrayList(); File configDir = new File(configDirPath); if (!configDir.exists()) - throw new VOMSConfigurationException( - "Voms configuration directory does not exist"); + throw new VOMSConfigurationException("Voms configuration directory does not exist"); File[] filez = configDir.listFiles(); @@ -571,8 +533,7 @@ public List getLocallyConfiguredVOs() { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getLong(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getLong(java.lang.String) */ public long getLong(String arg0) { @@ -582,9 +543,7 @@ public long getLong(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getLong(java.lang.String, - * long) + * @see org.apache.commons.configuration.Configuration#getLong(java.lang.String, long) */ public long getLong(String arg0, long arg1) { @@ -594,9 +553,7 @@ public long getLong(String arg0, long arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getLong(java.lang.String, - * java.lang.Long) + * @see org.apache.commons.configuration.Configuration#getLong(java.lang.String, java.lang.Long) */ public Long getLong(String arg0, Long arg1) { @@ -606,8 +563,7 @@ public Long getLong(String arg0, Long arg1) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getProperties(java.lang - * .String) + * @see org.apache.commons.configuration.Configuration#getProperties(java.lang .String) */ public Properties getProperties(String arg0) { @@ -617,8 +573,7 @@ public Properties getProperties(String arg0) { /* * (non-Javadoc) * - * @see org.apache.commons.configuration.Configuration#getProperty(java.lang. - * String) + * @see org.apache.commons.configuration.Configuration#getProperty(java.lang. String) */ public Object getProperty(String arg0) { @@ -648,8 +603,7 @@ public ServletContext getServletContext() { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getShort(java.lang.String) + * @see org.apache.commons.configuration.Configuration#getShort(java.lang.String) */ public short getShort(String arg0) { @@ -659,9 +613,7 @@ public short getShort(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getShort(java.lang.String, - * short) + * @see org.apache.commons.configuration.Configuration#getShort(java.lang.String, short) */ public short getShort(String arg0, short arg1) { @@ -671,9 +623,7 @@ public short getShort(String arg0, short arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getShort(java.lang.String, - * java.lang.Short) + * @see org.apache.commons.configuration.Configuration#getShort(java.lang.String, java.lang.Short) */ public Short getShort(String arg0, Short arg1) { @@ -683,8 +633,7 @@ public Short getShort(String arg0, Short arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getString(java.lang.String ) + * @see org.apache.commons.configuration.Configuration#getString(java.lang.String ) */ public String getString(String arg0) { @@ -694,8 +643,7 @@ public String getString(String arg0) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getString(java.lang.String , + * @see org.apache.commons.configuration.Configuration#getString(java.lang.String , * java.lang.String) */ public String getString(String arg0, String arg1) { @@ -706,9 +654,7 @@ public String getString(String arg0, String arg1) { /* * (non-Javadoc) * - * @see - * org.apache.commons.configuration.Configuration#getStringArray(java.lang - * .String) + * @see org.apache.commons.configuration.Configuration#getStringArray(java.lang .String) */ public String[] getStringArray(String arg0) { @@ -751,30 +697,27 @@ public boolean isEmpty() { private void loadServiceCredentials() { - String certificateFileName = getString( - VOMSConfigurationConstants.VOMS_SERVICE_CERT_FILE, - "/etc/grid-security/hostcert.pem"); + String certificateFileName = getString(VOMSConfigurationConstants.VOMS_SERVICE_CERT_FILE, + "/etc/grid-security/hostcert.pem"); - String privateKeyFileName = getString( - VOMSConfigurationConstants.VOMS_SERVICE_KEY_FILE, - "/etc/grid-security/hostkey.pem"); + String privateKeyFileName = getString(VOMSConfigurationConstants.VOMS_SERVICE_KEY_FILE, + "/etc/grid-security/hostkey.pem"); /* load certificate */ - log.info("Loading credentials for VOMS Attribute authority from:" - + certificateFileName + "," + privateKeyFileName); + log.info("Loading credentials for VOMS Attribute authority from:" + certificateFileName + "," + + privateKeyFileName); try { - serviceCredential = new PEMCredential( - new FileInputStream(privateKeyFileName), - new FileInputStream(certificateFileName), (char[]) null); + serviceCredential = new PEMCredential(new FileInputStream(privateKeyFileName), + new FileInputStream(certificateFileName), (char[]) null); } catch (Throwable t) { log.error("Error loading service credentials: {}", t.getMessage(), t); throw new VOMSException(t.getMessage(), t); } - log.info("VOMS AA service credential's DN: " + DNUtil.getOpenSSLSubject( - serviceCredential.getCertificate().getSubjectX500Principal())); + log.info("VOMS AA service credential's DN: " + + DNUtil.getOpenSSLSubject(serviceCredential.getCertificate().getSubjectX500Principal())); } @@ -784,8 +727,8 @@ public void loadServiceProperties() { try { - PropertiesConfiguration vomsServiceProperties = new PropertiesConfiguration( - getVomsServicePropertiesFileName()); + PropertiesConfiguration vomsServiceProperties = + new PropertiesConfiguration(getVomsServicePropertiesFileName()); config.addConfiguration(vomsServiceProperties); } catch (ConfigurationException e) { @@ -794,8 +737,7 @@ public void loadServiceProperties() { if (log.isDebugEnabled()) log.error(e.getMessage(), e); - throw new VOMSConfigurationException( - "Error loading service properties from " + fileName, e); + throw new VOMSConfigurationException("Error loading service properties from " + fileName, e); } @@ -811,28 +753,24 @@ private void loadSysconfig() { sysconfigFilePath = SysconfigUtil.getSysconfigFilePath(); - PropertiesConfiguration sysconf = new PropertiesConfiguration( - sysconfigFilePath); + PropertiesConfiguration sysconf = new PropertiesConfiguration(sysconfigFilePath); config.addConfiguration(sysconf); log.debug("Loaded sysconfig from: {}", sysconfigFilePath); } catch (ConfigurationException e) { - log.error("Error parsing VOMS Admin system configuration file " - + sysconfigFilePath); + log.error("Error parsing VOMS Admin system configuration file " + sysconfigFilePath); throw new VOMSConfigurationException( - "Error parsing VOMS Admin system configuration file " - + SYSCONFIG_DEFAULT_FILE_PATH, - e); + "Error parsing VOMS Admin system configuration file " + SYSCONFIG_DEFAULT_FILE_PATH, e); } } private void loadVersionProperties() { - InputStream versionPropStream = this.getClass().getClassLoader() - .getResourceAsStream("version.properties"); + InputStream versionPropStream = + this.getClass().getClassLoader().getResourceAsStream("version.properties"); PropertiesConfiguration versionProperties = new PropertiesConfiguration(); try { @@ -843,8 +781,7 @@ private void loadVersionProperties() { } catch (ConfigurationException e) { log.error("Error configuring version properties:" + e.getMessage(), e); - throw new VOMSConfigurationException( - "Error configuring version properties!", e); + throw new VOMSConfigurationException("Error configuring version properties!", e); } } @@ -874,9 +811,8 @@ private List stringListToIntegerList(List list) { int ii = Integer.parseInt(i.trim()); timeList.add(ii); } catch (NumberFormatException nfe) { - throw new VOMSException( - "Error while parsing list '" + list + "': " + nfe.getMessage(), - nfe); + throw new VOMSException("Error while parsing list '" + list + "': " + nfe.getMessage(), + nfe); } } @@ -886,14 +822,12 @@ private List stringListToIntegerList(List list) { public List getAUPReminderIntervals() { - int signAUPTaskLifetime = config.getInteger( - VOMSConfigurationConstants.SIGN_AUP_TASK_LIFETIME, - VOMSConfigurationConstants.SIGN_AUP_TASK_LIFETIME_DEFAULT_VALUE); + int signAUPTaskLifetime = config.getInteger(VOMSConfigurationConstants.SIGN_AUP_TASK_LIFETIME, + VOMSConfigurationConstants.SIGN_AUP_TASK_LIFETIME_DEFAULT_VALUE); @SuppressWarnings("unchecked") - List reminderTimes = config.getList( - VOMSConfigurationConstants.SIGN_AUP_TASK_REMINDERS, Arrays.asList( - VOMSConfigurationConstants.SIGN_AUP_TASK_REMINDERS_DEFAULT_VALUE)); + List reminderTimes = config.getList(VOMSConfigurationConstants.SIGN_AUP_TASK_REMINDERS, + Arrays.asList(VOMSConfigurationConstants.SIGN_AUP_TASK_REMINDERS_DEFAULT_VALUE)); List intervals = stringListToIntegerList(reminderTimes); @@ -921,8 +855,7 @@ private String loadVomsesConfigurationString() { try { - String vomsesConf = FileUtils - .readFileToString(new File(vomsesConfFileName)); + String vomsesConf = FileUtils.readFileToString(new File(vomsesConfFileName)); return vomsesConf; } catch (IOException e) { @@ -940,11 +873,9 @@ private void loadVOName() { if (!config.containsKey("VO_NAME")) { if (context.getInitParameter("VO_NAME") != null) { - log.debug("Setting VO name from init parameter: {}", - context.getInitParameter("VO_NAME")); + log.debug("Setting VO name from init parameter: {}", context.getInitParameter("VO_NAME")); - config.setProperty(VOMSConfigurationConstants.VO_NAME, - context.getInitParameter("VO_NAME")); + config.setProperty(VOMSConfigurationConstants.VO_NAME, context.getInitParameter("VO_NAME")); } @@ -954,8 +885,7 @@ private void loadVOName() { } else { - config.setProperty(VOMSConfigurationConstants.VO_NAME, - config.getProperty("VO_NAME")); + config.setProperty(VOMSConfigurationConstants.VO_NAME, config.getProperty("VO_NAME")); } } @@ -982,36 +912,32 @@ public Configuration subset(String arg0) { @SuppressWarnings("unchecked") public List getExternalValidators() { - return config - .getList(VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_LIST); + return config.getList(VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_LIST); } public String getExternalValidatorConfigClass(String pluginName) { - String configClassPropertyName = String.format("%s.%s.%s", - VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, pluginName, - VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_CONFIG_SUFFIX); + String configClassPropertyName = + String.format("%s.%s.%s", VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, + pluginName, VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_CONFIG_SUFFIX); return config.getString(configClassPropertyName); } - public String getExternalValidatorProperty(String pluginName, - String pluginPropertyName, String defaultValue) { + public String getExternalValidatorProperty(String pluginName, String pluginPropertyName, + String defaultValue) { String propertyName = String.format("%s.%s.%s", - VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, pluginName, - pluginPropertyName); + VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, pluginName, pluginPropertyName); return config.getString(propertyName, defaultValue); } - public String getExternalValidatorProperty(String pluginName, - String pluginPropertyName) { + public String getExternalValidatorProperty(String pluginName, String pluginPropertyName) { String propertyName = String.format("%s.%s.%s", - VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, pluginName, - pluginPropertyName); + VOMSConfigurationConstants.VOMS_EXTERNAL_VALIDATOR_PREFIX, pluginName, pluginPropertyName); return config.getString(propertyName); @@ -1019,22 +945,20 @@ public String getExternalValidatorProperty(String pluginName, public void setRegistrationType(String registrationType) { - config.setProperty( - VOMSConfigurationConstants.VOMS_INTERNAL_REGISTRATION_TYPE, - registrationType); + config.setProperty(VOMSConfigurationConstants.VOMS_INTERNAL_REGISTRATION_TYPE, + registrationType); } public String getRegistrationType() { - return config.getString( - VOMSConfigurationConstants.VOMS_INTERNAL_REGISTRATION_TYPE, "default"); + return config.getString(VOMSConfigurationConstants.VOMS_INTERNAL_REGISTRATION_TYPE, "default"); } public VOMSPermission getUnauthenticatedClientPermissionMask() { - String unauthenticatedClientPermMask = getString( - VOMSConfigurationConstants.VOMS_UNAUTHENTICATED_CLIENT_PERMISSION_MASK, - "CONTAINER_READ|MEMBERSHIP_READ"); + String unauthenticatedClientPermMask = + getString(VOMSConfigurationConstants.VOMS_UNAUTHENTICATED_CLIENT_PERMISSION_MASK, + "CONTAINER_READ|MEMBERSHIP_READ"); VOMSPermission permMask = null; @@ -1044,12 +968,10 @@ public VOMSPermission getUnauthenticatedClientPermissionMask() { } catch (IllegalArgumentException e) { // Parse error on user set permission mask - log.error( - "Error parsing user set permission mask for unauthenticated client: '" + log.error("Error parsing user set permission mask for unauthenticated client: '" + unauthenticatedClientPermMask + "'"); log.error(e.getMessage()); - permMask = VOMSPermission.getContainerReadPermission() - .setMembershipReadPermission(); + permMask = VOMSPermission.getContainerReadPermission().setMembershipReadPermission(); } @@ -1059,21 +981,19 @@ public VOMSPermission getUnauthenticatedClientPermissionMask() { public String getServiceHostname() { - return config.getString(VOMSConfigurationConstants.VOMS_SERVICE_HOSTNAME, - "localhost"); + return config.getString(VOMSConfigurationConstants.VOMS_SERVICE_HOSTNAME, "localhost"); } public String getGroupManagerRoleName() { - return config.getString(VOMSConfigurationConstants.GROUP_MANAGER_ROLE_NAME, - "Group-Manager"); + return config.getString(VOMSConfigurationConstants.GROUP_MANAGER_ROLE_NAME, "Group-Manager"); } public int getExpiringUsersWarningInterval() { - String warningPeriodInDays = VOMSConfiguration.instance().getString( - VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD, - VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); + String warningPeriodInDays = VOMSConfiguration.instance() + .getString(VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD, + VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); Integer i; @@ -1084,22 +1004,21 @@ public int getExpiringUsersWarningInterval() { } catch (NumberFormatException e) { log.error( - "Error converting {} to an integer. The {} property should contain a positive integer! Using the default value instead.", - warningPeriodInDays); + "Error converting {} to an integer. The {} property should contain a positive integer! Using the default value instead.", + warningPeriodInDays); - return Integer.parseInt( - VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); + return Integer + .parseInt(VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); } if (i <= 0) { - log.warn( - "Negative warning period set for the property {}. Using the default value instead.", - VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD); + log.warn("Negative warning period set for the property {}. Using the default value instead.", + VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD); - return Integer.parseInt( - VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); + return Integer + .parseInt(VOMSConfigurationConstants.MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE); } return i; @@ -1119,11 +1038,18 @@ public PEMCredential getServiceCredential() { return serviceCredential; } - + public boolean permissionCacheDisabled() { return config.getBoolean(PERMISSION_CACHE_DISABLE, false); } + public Set getRequiredPersonalInfoFields() { + String requiredFields = + config.getString(PI_REQUIRED_FIELDS, VOMSConfigurationConstants.PI_REQUIRED_FIELDS_DEFAULT); + + return Sets.newHashSet(Splitter.on(",").trimResults().omitEmptyStrings().split(requiredFields)); + } + public void dump(PrintStream stream) { for (int i = 0; i < config.getNumberOfConfigurations(); i++) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java index 9b65a9bf..65c4cb77 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java @@ -177,4 +177,11 @@ public interface VOMSConfigurationConstants { * Should permission cache be disabled? */ public static final String PERMISSION_CACHE_DISABLE = "voms.permission_cache.disable"; + + /** + * comma-separated list of the personal information fields required at registration + */ + public static final String PI_REQUIRED_FIELDS = "voms.personal_info.required_fields"; + + public static final String PI_REQUIRED_FIELDS_DEFAULT = "institution,address,phoneNumber"; } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java index 96032a03..7a3003be 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java @@ -16,6 +16,9 @@ package org.glite.security.voms.admin.integration.cern; import static java.util.Objects.isNull; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.PI_REQUIRED_FIELDS; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.VOMS_INTERNAL_RO_PERSONAL_INFORMATION; import java.io.File; import java.io.FileInputStream; @@ -27,7 +30,6 @@ import java.util.concurrent.TimeUnit; import org.glite.security.voms.admin.configuration.VOMSConfiguration; -import org.glite.security.voms.admin.configuration.VOMSConfigurationConstants; import org.glite.security.voms.admin.core.tasks.DatabaseTransactionTaskWrapper; import org.glite.security.voms.admin.core.tasks.VOMSExecutorService; import org.glite.security.voms.admin.core.validation.ValidationManager; @@ -156,11 +158,13 @@ public void configure() throws VOMSPluginConfigurationException { VOMSConfiguration config = getVomsConfig(); config.setRegistrationType(HR_DB_REGISTRATION_TYPE); - config.setProperty(VOMSConfigurationConstants.VOMS_INTERNAL_RO_PERSONAL_INFORMATION, + config.setProperty(VOMS_INTERNAL_RO_PERSONAL_INFORMATION, Boolean.TRUE); - config.setProperty(VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, + config.setProperty(VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, Boolean.TRUE); + config.setProperty(PI_REQUIRED_FIELDS, ""); + HrDbApiService api = apiServiceFactory.newHrDbApiService(hrConfig); validationManager diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java index 2e5438fc..c0a9592d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/OrgDBConfigurator.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.integration.orgdb; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.PI_REQUIRED_FIELDS; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -152,6 +154,8 @@ public synchronized void configure() throws VOMSPluginConfigurationException { VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, Boolean.TRUE); + VOMSConfiguration.instance().setProperty(PI_REQUIRED_FIELDS, ""); + log.info("OrgDB request validator registered SUCCESSFULLY."); Long checkPeriod; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/StartAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/StartAction.java index 9fdc7f27..229ba0b3 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/StartAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/StartAction.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.view.actions.register; +import java.util.Set; + import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import org.glite.security.voms.admin.configuration.VOMSConfiguration; @@ -40,6 +42,17 @@ public class StartAction extends RegisterActionSupport { */ private static final long serialVersionUID = 1L; + private Set requiredFields; + + public Set getRequiredFields() { + return requiredFields; + } + + @Override + public void prepare() throws Exception { + super.prepare(); + requiredFields = VOMSConfiguration.instance().getRequiredPersonalInfoFields(); + } @Override public String execute() throws Exception { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/SubmitRequestAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/SubmitRequestAction.java index 35f9daf9..b547ee6b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/SubmitRequestAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/SubmitRequestAction.java @@ -17,6 +17,7 @@ import java.util.Calendar; import java.util.Date; +import java.util.Set; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.Result; @@ -31,6 +32,7 @@ import org.glite.security.voms.admin.util.URLBuilder; import org.glite.security.voms.admin.view.actions.BaseAction; +import com.google.common.base.Strings; import com.opensymphony.xwork2.validator.annotations.EmailValidator; import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator; @@ -71,6 +73,18 @@ public class SubmitRequestAction extends RegisterActionSupport { String userMessage; RequestValidationResult validationResult; + + Set requiredFields; + + public Set getRequiredFields() { + return requiredFields; + } + + @Override + public void prepare() throws Exception { + super.prepare(); + requiredFields = VOMSConfiguration.instance().getRequiredPersonalInfoFields(); + } protected void populateRequestModel() { @@ -153,8 +167,6 @@ public void setSurname(String surname) { this.surname = surname; } - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter your institution.") @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>=;]*$", message = "You entered invalid characters.") public String getInstitution() { @@ -167,8 +179,6 @@ public void setInstitution(String institution) { this.institution = institution; } - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter your address.") @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", message = "You entered invalid characters.") public String getAddress() { @@ -181,8 +191,6 @@ public void setAddress(String address) { this.address = address; } - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter your phone number.") @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", message = "You entered invalid characters.") public String getPhoneNumber() { @@ -243,4 +251,19 @@ public RequestValidationResult getValidationResult() { return validationResult; } + @Override + public void validate() { + + if (requiredFields.contains("institution") && Strings.isNullOrEmpty(institution)) { + addFieldError("institution", "Please provide a value for the institution"); + } + + if (requiredFields.contains("address") && Strings.isNullOrEmpty(address)) { + addFieldError("address", "Please provide a value for the address"); + } + + if (requiredFields.contains("phoneNumber") && Strings.isNullOrEmpty(phoneNumber)) { + addFieldError("phoneNumber", "Please provide a value for the phoneNumber"); + } + } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/orgdb/SubmitRequestAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/orgdb/SubmitRequestAction.java index bbd12939..e0c39d9d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/orgdb/SubmitRequestAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/orgdb/SubmitRequestAction.java @@ -180,8 +180,6 @@ public void setInstitution(String institution) { /** * @return the address */ - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter your address.") @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", message = "You entered invalid characters.") public String getAddress() { @@ -201,8 +199,6 @@ public void setAddress(String address) { /** * @return the phoneNumber */ - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter your phoneNumber.") @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", message = "You entered invalid characters.") public String getPhoneNumber() { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/HomeAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/HomeAction.java index 0b7869eb..d3c45f84 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/HomeAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/HomeAction.java @@ -33,6 +33,8 @@ public class HomeAction extends UserActionSupport { @Override public void prepare() throws Exception { + super.prepare(); + if (CurrentAdmin.instance() .getVoUser() == null) { addActionError( diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java index 960f301d..07c67696 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java @@ -30,23 +30,21 @@ import org.glite.security.voms.admin.integration.orgdb.strategies.OrgDBEmailValidationResult; import org.glite.security.voms.admin.operations.users.SaveUserPersonalInfoOperation; +import com.google.common.base.Strings; import com.opensymphony.xwork2.validator.annotations.EmailValidator; import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; import com.opensymphony.xwork2.validator.annotations.ValidatorType; -@Results({ - @Result(name = UserActionSupport.SUCCESS, location = "personalInfo.jsp"), - @Result(name = UserActionSupport.INPUT, location = "personalInfo.jsp"), - @Result(name = TokenInterceptor.INVALID_TOKEN_CODE, - location = "personalInfo.jsp") }) -@InterceptorRef(value = "authenticatedStack", params = { - "token.includeMethods", "execute" }) +@Results({@Result(name = UserActionSupport.SUCCESS, location = "personalInfo.jsp"), + @Result(name = UserActionSupport.INPUT, location = "personalInfo.jsp"), + @Result(name = TokenInterceptor.INVALID_TOKEN_CODE, location = "personalInfo.jsp")}) +@InterceptorRef(value = "authenticatedStack", params = {"token.includeMethods", "execute"}) public class SavePersonalInformationAction extends UserActionSupport { /** - * - */ + * + */ private static final long serialVersionUID = 1L; String theName; @@ -56,45 +54,59 @@ public class SavePersonalInformationAction extends UserActionSupport { String thePhoneNumber; String theEmailAddress; - private static final String[] ORGDB_VALIDATED_FIELDS = { - "theAddress", - "thePhoneNumber" - }; - + private static final String[] ORGDB_VALIDATED_FIELDS = {"theAddress", "thePhoneNumber"}; + private boolean isOrgDBPluginEnabled() { - return VOMSConfiguration.instance().getRegistrationType() + return VOMSConfiguration.instance() + .getRegistrationType() .equals(OrgDBConfigurator.ORGDB_REGISTRATION_TYPE); } - + + protected void validateRequiredFields() { + + if (requiredFields.contains("institution") && Strings.isNullOrEmpty(theInstitution)) { + addFieldError("theInstitution", "Please provide a value for the institution"); + } + + if (requiredFields.contains("address") && Strings.isNullOrEmpty(theAddress)) { + addFieldError("theAddress", "Please provide a value for the address"); + } + + if (requiredFields.contains("phoneNumber") && Strings.isNullOrEmpty(thePhoneNumber)) { + addFieldError("thePhoneNumber", "Please provide a value for the phoneNumber"); + } + } @Override public void validate() { // Run default checks before orgdb checks super.validate(); - - if (hasFieldErrors()){ - - if (!isOrgDBPluginEnabled()){ + + validateRequiredFields(); + + if (hasFieldErrors()) { + + if (!isOrgDBPluginEnabled()) { return; } - + Map> fieldErrors = getFieldErrors(); - + clearFieldErrors(); - + // Retain only errors in the given fields fieldErrors.keySet().retainAll(Arrays.asList(ORGDB_VALIDATED_FIELDS)); - + // Add those errors back to the set of field errors - for (Map.Entry> e: fieldErrors.entrySet()){ - for (String msg: e.getValue()){ + for (Map.Entry> e : fieldErrors.entrySet()) { + for (String msg : e.getValue()) { addFieldError(e.getKey(), msg); } } - - if (hasFieldErrors()){ + + if (hasFieldErrors()) { return; } } @@ -104,12 +116,12 @@ public void validate() { OrgDBConfigurator conf = (OrgDBConfigurator) PluginManager.instance() .getConfiguredPlugin(OrgDBConfigurator.class.getName()); - if (conf == null) - throw new IllegalStateException( - "OrgDB plugin configured but configurator is null!"); + if (conf == null) { + throw new IllegalStateException("OrgDB plugin configured but configurator is null!"); + } - OrgDBEmailValidationResult validationResult = conf.getEmailValidator() - .validateEmailAddress(getModel(), getTheEmailAddress()); + OrgDBEmailValidationResult validationResult = + conf.getEmailValidator().validateEmailAddress(getModel(), getTheEmailAddress()); if (!validationResult.isValid()) { addActionError(validationResult.getValidationError()); @@ -120,9 +132,8 @@ public void validate() { @Override public String execute() throws Exception { - SaveUserPersonalInfoOperation op = new SaveUserPersonalInfoOperation( - getModel(), theName, theSurname, theInstitution, theAddress, - thePhoneNumber, theEmailAddress); + SaveUserPersonalInfoOperation op = new SaveUserPersonalInfoOperation(getModel(), theName, + theSurname, theInstitution, theAddress, thePhoneNumber, theEmailAddress); op.setAuthorizedUser(getModel()); @@ -132,9 +143,9 @@ public String execute() throws Exception { return SUCCESS; } + @RequiredStringValidator(type = ValidatorType.FIELD, message = "Please provide a value.") @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The name field contains illegal characters!", - regex = "^[^<>&=;]*$") + message = "The name field contains illegal characters!", regex = "^[^<>&=;]*$") public String getTheName() { return theName; @@ -145,9 +156,9 @@ public void setTheName(String theName) { this.theName = theName; } + @RequiredStringValidator(type = ValidatorType.FIELD, message = "Please provide a value.") @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The surname field contains illegal characters!", - regex = "^[^<>&=;]*$") + message = "The surname field contains illegal characters!", regex = "^[^<>&=;]*$") public String getTheSurname() { return theSurname; @@ -159,8 +170,7 @@ public void setTheSurname(String theSurname) { } @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The institution field contains illegal characters!", - regex = "^[^<>=;]*$") + message = "The institution field contains illegal characters!", regex = "^[^<>=;]*$") public String getTheInstitution() { return theInstitution; @@ -172,8 +182,7 @@ public void setTheInstitution(String theInstitution) { } @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The address field contains illegal characters!", - regex = "^[^<>&=;]*$") + message = "The address field contains illegal characters!", regex = "^[^<>&=;]*$") public String getTheAddress() { return theAddress; @@ -185,8 +194,7 @@ public void setTheAddress(String theAddress) { } @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The phoneNumber field contains illegal characters!", - regex = "^[^<>&=;]*$") + message = "The phoneNumber field contains illegal characters!", regex = "^[^<>&=;]*$") public String getThePhoneNumber() { return thePhoneNumber; @@ -197,13 +205,10 @@ public void setThePhoneNumber(String thePhoneNumber) { this.thePhoneNumber = thePhoneNumber; } - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please enter an email address.") - @EmailValidator(type = ValidatorType.FIELD, - message = "Please enter a valid email address.") + @RequiredStringValidator(type = ValidatorType.FIELD, message = "Please enter an email address.") + @EmailValidator(type = ValidatorType.FIELD, message = "Please enter a valid email address.") @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The email field name contains illegal characters!", - regex = "^[^<>&=;]*$") + message = "The email field name contains illegal characters!", regex = "^[^<>&=;]*$") public String getTheEmailAddress() { return theEmailAddress; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/UserActionSupport.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/UserActionSupport.java index d5105e00..e8a5349b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/UserActionSupport.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/UserActionSupport.java @@ -17,8 +17,10 @@ import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.struts2.interceptor.SessionAware; +import org.glite.security.voms.admin.configuration.VOMSConfiguration; import org.glite.security.voms.admin.persistence.dao.generic.DAOFactory; import org.glite.security.voms.admin.persistence.dao.generic.RequestDAO; import org.glite.security.voms.admin.persistence.model.AUP; @@ -62,6 +64,8 @@ public class UserActionSupport extends BaseAction implements protected List pendingMembershipRemovalRequests; protected Map theSession; + + protected Set requiredFields; public VOMSUser getModel() { @@ -88,7 +92,8 @@ public void prepare() throws Exception { if (getModel() != null){ refreshPendingRequests(); } - + + requiredFields = VOMSConfiguration.instance().getRequiredPersonalInfoFields(); } public Long getUserId() { @@ -165,4 +170,8 @@ public boolean hasValidAUPAcceptanceRecord() { .getValid() == true); } + + public Set getRequiredFields() { + return requiredFields; + } } diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/register/default/registration.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/register/default/registration.jsp index a65cb3af..de2d8d1f 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/register/default/registration.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/register/default/registration.jsp @@ -24,7 +24,7 @@ Welcome to the registration page for the ${voName} V

To access the VO resources, you must agree to the VO's Acceptable Usage Policy (AUP) rules.
-Please fill out all fields in the form below and click on the submit +Please fill out all the fields in the form below and click on the submit button at the bottom of the page.

@@ -62,15 +62,23 @@ button at the bottom of the page.
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • + +
  • + +
  • +
    + +
  • + +
  • +
    + + +
  • + +
  • +
    +
  • diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/register/orgdb/registration2.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/register/orgdb/registration2.jsp index 77ac539f..294490a4 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/register/orgdb/registration2.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/register/orgdb/registration2.jsp @@ -24,7 +24,7 @@ Welcome to the registration page for the ${voName} V

    To access the VO resources, you must agree to the VO's Acceptable Usage Policy (AUP) rules.
    -Please fill out all fields in the form below and click on the submit +Please fill out all the fields in the form below and click on the submit button at the bottom of the page.

    @@ -64,12 +64,6 @@ used to contact you in relation to this activity.

  • -
  • - -
  • -
  • - -
  • diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp index 356b6554..3d9a4c86 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/certificates.jsp @@ -55,16 +55,17 @@ var="thisCertCA" />${thisCertCA}
    - +
    Added on:
    +
    + +
    -
    - -
    +
    diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/personalInfo.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/personalInfo.jsp index 792b4a69..28915562 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/personalInfo.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/personalInfo.jsp @@ -16,49 +16,38 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + You do not have the rights to see the personal information for this user.
    \ No newline at end of file diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp index aef83f70..df98e430 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/requestHistory.jsp @@ -19,7 +19,7 @@ - + diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp index fd2769e2..f10aae2f 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp @@ -20,7 +20,7 @@
    - +
    diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp index 264335a3..3ea0023c 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userInfo.jsp @@ -17,12 +17,17 @@ --%> <%@include file="/WEB-INF/p/shared/taglibs.jsp"%> - +
    + +
    + you +
    +
    From e5fd75e288fceed1d78044c0bf0dd0877295c232 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 20 Dec 2019 19:50:19 +0100 Subject: [PATCH 38/63] Preliminary support for expired user periodic cleanup --- .../VOMSConfigurationConstants.java | 5 ++ .../security/voms/admin/core/VOMSService.java | 7 ++ .../CleanupUserLookupStrategy.java | 24 +++++++ .../DefaultCleanupUserLookupStrategy.java | 48 +++++++++++++ .../user_cleanup/ExpiredUserCleanupTask.java | 68 +++++++++++++++++++ .../admin/event/user/UserCleanedUpEvent.java | 29 ++++++++ .../admin/persistence/dao/VOMSUserDAO.java | 19 ++++++ 7 files changed, 200 insertions(+) create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/CleanupUserLookupStrategy.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/DefaultCleanupUserLookupStrategy.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/event/user/UserCleanedUpEvent.java diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java index 65c4cb77..42cde558 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java @@ -184,4 +184,9 @@ public interface VOMSConfigurationConstants { public static final String PI_REQUIRED_FIELDS = "voms.personal_info.required_fields"; public static final String PI_REQUIRED_FIELDS_DEFAULT = "institution,address,phoneNumber"; + + public static final String EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD= "voms.expired_user_cleanup_task.run_period_sec"; + + public static final String EXPIRED_USER_CLEANUP_TASK_CLEANUP_AFTER_DAYS= "voms.expired_user_cleanup_task.cleanup_after_days"; + } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java index c68d57ee..d72f255f 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java @@ -15,6 +15,7 @@ */ package org.glite.security.voms.admin.core; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD; import static org.glite.security.voms.admin.core.VOMSServiceConstants.DISABLE_BACKGROUND_TASK_PROPERTY; import java.io.File; @@ -44,6 +45,8 @@ import org.glite.security.voms.admin.core.tasks.UpdateCATask; import org.glite.security.voms.admin.core.tasks.UserStatsTask; import org.glite.security.voms.admin.core.tasks.VOMSExecutorService; +import org.glite.security.voms.admin.core.tasks.user_cleanup.DefaultCleanupUserLookupStrategy; +import org.glite.security.voms.admin.core.tasks.user_cleanup.ExpiredUserCleanupTask; import org.glite.security.voms.admin.core.validation.ValidationManager; import org.glite.security.voms.admin.error.VOMSFatalException; import org.glite.security.voms.admin.event.DebugEventLogListener; @@ -215,6 +218,10 @@ protected static void startBackgroundTasks() { es.scheduleAtFixedRate(new PermissionCacheStatsLogger(true), 1, 60, TimeUnit.SECONDS); + ExpiredUserCleanupTask userCleanupTask = new ExpiredUserCleanupTask(new DefaultCleanupUserLookupStrategy(conf)); + + es.startBackgroundTask(userCleanupTask, EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD, TimeUnit.HOURS.toSeconds(4)); + } protected static void startNotificationService() { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/CleanupUserLookupStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/CleanupUserLookupStrategy.java new file mode 100644 index 00000000..d3553b93 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/CleanupUserLookupStrategy.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.core.tasks.user_cleanup; + +import org.hibernate.ScrollableResults; + +public interface CleanupUserLookupStrategy { + + ScrollableResults findUsersEligibleForCleanup(); + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/DefaultCleanupUserLookupStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/DefaultCleanupUserLookupStrategy.java new file mode 100644 index 00000000..4f13b79d --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/DefaultCleanupUserLookupStrategy.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.core.tasks.user_cleanup; + +import static java.util.Objects.isNull; +import static org.glite.security.voms.admin.configuration.VOMSConfigurationConstants.EXPIRED_USER_CLEANUP_TASK_CLEANUP_AFTER_DAYS; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.hibernate.ScrollableResults; + +public class DefaultCleanupUserLookupStrategy implements CleanupUserLookupStrategy { + + VOMSConfiguration config; + VOMSUserDAO dao; + + public DefaultCleanupUserLookupStrategy(VOMSConfiguration config) { + this.config = config; + } + + @Override + public ScrollableResults findUsersEligibleForCleanup() { + + if (isNull(dao)) { + dao = VOMSUserDAO.instance(); + } + int numberOfDays = config.getInt(EXPIRED_USER_CLEANUP_TASK_CLEANUP_AFTER_DAYS, 30); + + return dao.findUsersExpiredSinceDays(numberOfDays); + } + + public void setDao(VOMSUserDAO dao) { + this.dao = dao; + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java new file mode 100644 index 00000000..80d6d77e --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.core.tasks.user_cleanup; + +import org.glite.security.voms.admin.core.tasks.RegistrationServiceTask; +import org.glite.security.voms.admin.event.EventManager; +import org.glite.security.voms.admin.event.user.UserCleanedUpEvent; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.hibernate.ScrollableResults; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExpiredUserCleanupTask implements Runnable, RegistrationServiceTask { + public static final Logger LOG = LoggerFactory.getLogger(ExpiredUserCleanupTask.class); + + final CleanupUserLookupStrategy lookupStrategy; + VOMSUserDAO dao; + EventManager eventManager; + + public ExpiredUserCleanupTask(CleanupUserLookupStrategy lookupStrategy) { + this.lookupStrategy = lookupStrategy; + } + + @Override + public void run() { + + if (dao == null) { + dao = VOMSUserDAO.instance(); + } + + if (eventManager == null) { + eventManager = EventManager.instance(); + } + + ScrollableResults userCursor = lookupStrategy.findUsersEligibleForCleanup(); + + while (userCursor.next()) { + VOMSUser user = (VOMSUser) userCursor.get(0); + + LOG.debug("Cleaning up user '{}' who expired on '{}'", user.getShortName(), + user.getEndTime()); + dao.delete(user); + eventManager.dispatch(new UserCleanedUpEvent(user)); + } + } + + public void setDao(VOMSUserDAO dao) { + this.dao = dao; + } + + public void setEventManager(EventManager eventManager) { + this.eventManager = eventManager; + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/user/UserCleanedUpEvent.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/user/UserCleanedUpEvent.java new file mode 100644 index 00000000..676cb5e7 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/event/user/UserCleanedUpEvent.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.event.user; + +import org.glite.security.voms.admin.event.EventDescription; +import org.glite.security.voms.admin.persistence.model.VOMSUser; + +@EventDescription(message = "cleaned up user '%s %s' whose membership expired on '%s'", + params = {"userName", "userSurname", "userMembershipExpirationDate"}) +public class UserCleanedUpEvent extends UserLifecycleEvent { + + public UserCleanedUpEvent(VOMSUser payload) { + super(payload); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index 98ce93d7..4059858d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -15,15 +15,18 @@ */ package org.glite.security.voms.admin.persistence.dao; +import static java.lang.Integer.max; import static org.glite.security.voms.admin.persistence.dao.SearchUtils.paginatedFind; import java.security.cert.X509Certificate; +import java.time.Instant; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.concurrent.TimeUnit; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; @@ -204,6 +207,22 @@ public Long countExpiredUsers() { } + public ScrollableResults findUsersExpiredSinceDays(int numberOfDays) { + + Instant now = Instant.now(); + + Instant then = now.minusSeconds(TimeUnit.DAYS.toSeconds(max(0, numberOfDays))); + String queryString = + "select distinct u from VOMSUser u where u.endTime is not null and u.endTime < :then and u.suspended = true"; + Query q = HibernateFactory.getSession().createQuery(queryString); + + q.setDate("then", Date.from(then)); + + q.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); + + return q.scroll(); + } + @SuppressWarnings("unchecked") public List findExpiredUsers() { From f1a896cda8f431ebd6fe1763acefaa3f13723056 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 7 Jan 2020 17:52:12 +0100 Subject: [PATCH 39/63] python2 shebang fixes Centos 7 comes with python2.7 by default. --- .../scripts/configure/voms_configure.py | 2 +- .../scripts/configure/voms_db_util.py | 109 ++++++---- .../scripts/configure/voms_mysql_util.py | 191 +++++++++++------- 3 files changed, 182 insertions(+), 120 deletions(-) diff --git a/voms-admin-server/resources/scripts/configure/voms_configure.py b/voms-admin-server/resources/scripts/configure/voms_configure.py index 482f1cbe..60e23c01 100644 --- a/voms-admin-server/resources/scripts/configure/voms_configure.py +++ b/voms-admin-server/resources/scripts/configure/voms_configure.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.6 +#!/usr/bin/env python2 # # Copyright (c) Members of the EGEE Collaboration. 2006-2009. # See http://www.eu-egee.org/partners/ for details on the copyright holders. diff --git a/voms-admin-server/resources/scripts/configure/voms_db_util.py b/voms-admin-server/resources/scripts/configure/voms_db_util.py index 06663068..712f880a 100644 --- a/voms-admin-server/resources/scripts/configure/voms_db_util.py +++ b/voms-admin-server/resources/scripts/configure/voms_db_util.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.6 +#!/usr/bin/env python2 # # Copyright (c) Members of the EGEE Collaboration. 2006-2009. # See http://www.eu-egee.org/partners/ for details on the copyright holders. @@ -19,12 +19,14 @@ # Andrea Ceccanti (INFN) # -import sys,string,os +import sys +import string +import os from sys import stderr, exit from optparse import OptionParser from voms_shared import VOMSDefaults, X509Helper, get_oracle_env -usage="""%prog [options] command +usage = """%prog [options] command Commands: check-connectivity: checks database connection @@ -40,33 +42,44 @@ """ parser = OptionParser(usage) -commands = ["deploy","undeploy","upgrade","check-connectivity","grant-read-only-access", "add-admin", "remove-admin"] +commands = ["deploy", "undeploy", "upgrade", "check-connectivity", + "grant-read-only-access", "add-admin", "remove-admin"] + def setup_cl_options(): - parser.add_option("--vo", dest="vo", help="the VO for which database operations are performed", metavar="VO") - parser.add_option("--dn", dest="admin_dn", help="the DN of the administrator certificate", metavar="DN") - parser.add_option("--ca", dest="admin_ca", help="the DN of the CA that issued the administrator certificate", metavar="DN") - parser.add_option("--email", dest="admin_email", help="the EMAIL address of the administrator", metavar="EMAIL") - parser.add_option("--cert", dest="admin_cert", help="the x.509 CERTIFICATE of the administrator being created", metavar="CERTIFICATE") - parser.add_option("--ignore-cert-email", dest="admin_ignore_cert_email", action="store_true", help="ignores the email address in the certificate passed in with the --cert option") + parser.add_option( + "--vo", dest="vo", help="the VO for which database operations are performed", metavar="VO") + parser.add_option("--dn", dest="admin_dn", + help="the DN of the administrator certificate", metavar="DN") + parser.add_option("--ca", dest="admin_ca", + help="the DN of the CA that issued the administrator certificate", metavar="DN") + parser.add_option("--email", dest="admin_email", + help="the EMAIL address of the administrator", metavar="EMAIL") + parser.add_option("--cert", dest="admin_cert", + help="the x.509 CERTIFICATE of the administrator being created", metavar="CERTIFICATE") + parser.add_option("--ignore-cert-email", dest="admin_ignore_cert_email", action="store_true", + help="ignores the email address in the certificate passed in with the --cert option") + def error_and_exit(msg): print >>stderr, msg exit(1) + def build_classpath(): - + jars = VOMSDefaults.voms_admin_libs - + if len(jars) == 0: raise ValueError, "voms-admin jar files not found!" - + jars.append(VOMSDefaults.voms_admin_jar) jars.append(VOMSDefaults.voms_admin_classes) - - return string.join(jars,":") -def do_basic_command(options,command): + return string.join(jars, ":") + + +def do_basic_command(options, command): cmd = "%s java -cp %s %s --command %s --vo %s" % (get_oracle_env(), build_classpath(), VOMSDefaults.schema_deployer_class, @@ -77,38 +90,39 @@ def do_basic_command(options,command): def do_add_admin(options): - + email = None - + if options.admin_cert: cert = X509Helper(options.admin_cert) dn = cert.subject ca = cert.issuer - + if not options.admin_ignore_cert_email: email = cert.email else: dn = options.admin_dn ca = options.admin_ca email = options.admin_email - + if not email: print "WARNING: No email was specified for this administrator! The new administrator will not receive VOMS Admin notifications" - + cmd = "%s java -cp %s %s --command add-admin --vo %s --dn '%s' --ca '%s'" % (get_oracle_env(), - build_classpath(), - VOMSDefaults.schema_deployer_class, - options.vo, - dn, - ca) + build_classpath(), + VOMSDefaults.schema_deployer_class, + options.vo, + dn, + ca) if email: cmd += " --email '%s' " % email - + status = os.system(cmd) sys.exit(os.WEXITSTATUS(status)) + def do_remove_admin(options): - + if options.admin_cert: cert = X509Helper(options.admin_cert) dn = cert.subject @@ -116,7 +130,7 @@ def do_remove_admin(options): else: dn = options.admin_dn ca = options.admin_ca - + cmd = "%s java -cp %s %s --command remove-admin --vo %s --dn '%s' --ca '%s' " % (get_oracle_env(), build_classpath(), VOMSDefaults.schema_deployer_class, @@ -126,29 +140,35 @@ def do_remove_admin(options): status = os.system(cmd) sys.exit(os.WEXITSTATUS(status)) -def check_args_and_options(options,args): + +def check_args_and_options(options, args): if len(args) != 1 or args[0] not in commands: - error_and_exit("Please specify a single command among the following:\n\t%s" % "\n\t".join(commands)) - + error_and_exit( + "Please specify a single command among the following:\n\t%s" % "\n\t".join(commands)) + if not options.vo: error_and_exit("Please specify a VO with the --vo option.") - - if args[0] in ("add-admin","remove-admin"): - + + if args[0] in ("add-admin", "remove-admin"): + if (not options.admin_dn or not options.admin_ca) and not options.admin_cert: - error_and_exit("Please specify an administrator either providing a certificate with the --cert option, or with the --dn and --ca options.") - + error_and_exit( + "Please specify an administrator either providing a certificate with the --cert option, or with the --dn and --ca options.") + if options.admin_cert and (options.admin_dn or options.admin_ca): - error_and_exit("The --cert option and --dn,--ca are mutually exclusive.") - + error_and_exit( + "The --cert option and --dn,--ca are mutually exclusive.") + if not options.admin_cert and options.admin_ignore_cert_email: - error_and_exit("The --ignore-cert-email must be used together with the --cert option.") + error_and_exit( + "The --ignore-cert-email must be used together with the --cert option.") + def main(): setup_cl_options() - (options,args) = parser.parse_args() + (options, args) = parser.parse_args() check_args_and_options(options, args) - + command = args[0] if command == "add-admin": @@ -157,6 +177,7 @@ def main(): do_remove_admin(options) else: do_basic_command(options, command) - + + if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/voms-admin-server/resources/scripts/configure/voms_mysql_util.py b/voms-admin-server/resources/scripts/configure/voms_mysql_util.py index 277cbec1..62a87609 100644 --- a/voms-admin-server/resources/scripts/configure/voms_mysql_util.py +++ b/voms-admin-server/resources/scripts/configure/voms_mysql_util.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.6 +#!/usr/bin/env python2 # # Copyright (c) Members of the EGEE Collaboration. 2006-2009. # See http://www.eu-egee.org/partners/ for details on the copyright holders. @@ -19,8 +19,11 @@ # Andrea Ceccanti (INFN) from optparse import OptionParser -from sys import stderr,exit -import subprocess,re, string, socket +from sys import stderr, exit +import subprocess +import re +import string +import socket usage = """%prog [options] command @@ -35,22 +38,35 @@ """ parser = OptionParser(usage=usage) + def setup_cl_options(): - parser.add_option("--dbauser", dest="dbauser", help="Sets MySQL administrator user to USER", metavar="USER", default="root") - parser.add_option("--dbapwd", dest="dbapwd", help="Sets MySQL administrator password to PWD", metavar="PWD") - parser.add_option("--dbapwdfile", dest="dbapwdfile", help="Reads MySQL administrator password from FILE", metavar="FILE") - parser.add_option("--dbusername", dest="username", help="Sets the VOMS MySQL username to be created as USER", metavar="USER") - parser.add_option("--vomshost", dest="voms_host", help="Sets the HOST where VOMS is running", metavar="HOST") - parser.add_option("--dbpassword", dest="password", help="Sets the VOMS MySQL password for the user to be created as PWD", metavar="PWD") - parser.add_option("--dbname", dest="dbname", help="Sets the VOMS database name to DBNAME", metavar="DBNAME") - parser.add_option("--dbhost",dest="host", help="Sets the HOST where MySQL is running", metavar="HOST", default="localhost") - parser.add_option("--dbport",dest="port", help="Sets the PORT where MySQL is listening", metavar="PORT", default="3306") - parser.add_option("--mysql-command", dest="command", help="Sets the MySQL command to CMD", metavar="CMD", default="mysql") + parser.add_option("--dbauser", dest="dbauser", + help="Sets MySQL administrator user to USER", metavar="USER", default="root") + parser.add_option("--dbapwd", dest="dbapwd", + help="Sets MySQL administrator password to PWD", metavar="PWD") + parser.add_option("--dbapwdfile", dest="dbapwdfile", + help="Reads MySQL administrator password from FILE", metavar="FILE") + parser.add_option("--dbusername", dest="username", + help="Sets the VOMS MySQL username to be created as USER", metavar="USER") + parser.add_option("--vomshost", dest="voms_host", + help="Sets the HOST where VOMS is running", metavar="HOST") + parser.add_option("--dbpassword", dest="password", + help="Sets the VOMS MySQL password for the user to be created as PWD", metavar="PWD") + parser.add_option("--dbname", dest="dbname", + help="Sets the VOMS database name to DBNAME", metavar="DBNAME") + parser.add_option("--dbhost", dest="host", + help="Sets the HOST where MySQL is running", metavar="HOST", default="localhost") + parser.add_option("--dbport", dest="port", + help="Sets the PORT where MySQL is listening", metavar="PORT", default="3306") + parser.add_option("--mysql-command", dest="command", + help="Sets the MySQL command to CMD", metavar="CMD", default="mysql") + def error_and_exit(msg): print >>stderr, msg exit(1) - + + def build_mysql_command_preamble(options): if options.dbapwdfile: try: @@ -59,7 +75,7 @@ def build_mysql_command_preamble(options): error_and_exit(e.strerror) else: dbapwd = options.dbapwd - + if not dbapwd: mysql_cmd = "%s -u%s --host %s --port %s" % (options.command, options.dbauser, @@ -73,19 +89,20 @@ def build_mysql_command_preamble(options): options.port) return mysql_cmd - def db_exists(options): mysql_cmd = build_mysql_command_preamble(options) - - mysql_proc = subprocess.Popen(mysql_cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + + mysql_proc = subprocess.Popen( + mysql_cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE) try: print >>mysql_proc.stdin, "use %s;" % options.dbname mysql_proc.stdin.close() except IOError as e: err_msg = mysql_proc.stderr.read() - error_and_exit("Error checking database existence: %s. %s" % (e, err_msg)) - + error_and_exit( + "Error checking database existence: %s. %s" % (e, err_msg)) + status = mysql_proc.wait() if status == 0: return True @@ -96,26 +113,30 @@ def db_exists(options): return False else: error_and_exit("Error checking schema existence: %s" % err_msg) - + + def create_db(options): print "Creating database %s" % options.dbname - + if db_exists(options): print "Schema for database %s already exists, will not create it..." % options.dbname else: mysql_cmd = build_mysql_command_preamble(options) - ## The database is not there, let's create it - mysql_proc = subprocess.Popen(mysql_cmd, shell=True, stdin=subprocess.PIPE) + # The database is not there, let's create it + mysql_proc = subprocess.Popen( + mysql_cmd, shell=True, stdin=subprocess.PIPE) print >>mysql_proc.stdin, "create database %s;" % options.dbname mysql_proc.stdin.close() status = mysql_proc.wait() if status != 0: - error_and_exit("Error creating MySQL database %s: %s" % (options.dbname, mysql_proc.stdout.read())) - + error_and_exit("Error creating MySQL database %s: %s" % + (options.dbname, mysql_proc.stdout.read())) + grant_rw_access(options) - + print "Done." + def drop_db(options): print "Dropping database %s" % options.dbname if not db_exists(options): @@ -123,55 +144,67 @@ def drop_db(options): exit(1) else: mysql_cmd = build_mysql_command_preamble(options) - mysql_proc = subprocess.Popen(mysql_cmd, shell=True, stdin=subprocess.PIPE) + mysql_proc = subprocess.Popen( + mysql_cmd, shell=True, stdin=subprocess.PIPE) print >>mysql_proc.stdin, "drop database %s;" % options.dbname mysql_proc.stdin.close() status = mysql_proc.wait() if status != 0: - error_and_exit("Error dropping MySQL database %s: %s" % (options.dbname, mysql_proc.stdout.read())) + error_and_exit("Error dropping MySQL database %s: %s" % + (options.dbname, mysql_proc.stdout.read())) print "Done." + def grant_rw_access(options): - print "Granting user %s read/write access on database %s" % (options.username, options.dbname) + print "Granting user %s read/write access on database %s" % ( + options.username, options.dbname) mysql_cmd = build_mysql_command_preamble(options) - + if len(options.username) > 16: - error_and_exit("MySQL database accont names cannot be longer than 16 characters.") - + error_and_exit( + "MySQL database accont names cannot be longer than 16 characters.") + if db_exists(options): - mysql_proc = subprocess.Popen(mysql_cmd, shell=True, stdin=subprocess.PIPE) - hosts = ['localhost','localhost.%',socket.gethostname(),socket.getfqdn()] - + mysql_proc = subprocess.Popen( + mysql_cmd, shell=True, stdin=subprocess.PIPE) + hosts = ['localhost', 'localhost.%', + socket.gethostname(), socket.getfqdn()] + if options.voms_host: - hosts = [options.voms_host,options.voms_host + '.%'] - + hosts = [options.voms_host, options.voms_host + '.%'] + for host in hosts: print >>mysql_proc.stdin, "grant all privileges on %s.* to '%s'@'%s' identified by '%s' with grant option;" % (options.dbname, - options.username, - host, - options.password) + options.username, + host, + options.password) print >>mysql_proc.stdin, "flush privileges;" mysql_proc.stdin.close() status = mysql_proc.wait() if status != 0: - error_and_exit("Error granting read/write access to user %s on database %s: %s" % (options.username, + error_and_exit("Error granting read/write access to user %s on database %s: %s" % (options.username, options.dbname, mysql_proc.stdout.read())) + def grant_ro_access(): - print "Granting user %s read-only access on database %s" % (options.username, options.dbname) + print "Granting user %s read-only access on database %s" % ( + options.username, options.dbname) mysql_cmd = build_mysql_command_preamble(options) - + if len(options.username) > 16: - error_and_exit("MySQL database accont names cannot be longer than 16 characters.") - + error_and_exit( + "MySQL database accont names cannot be longer than 16 characters.") + if db_exists(options): - mysql_proc = subprocess.Popen(mysql_cmd, shell=True, stdin=subprocess.PIPE) - hosts = ['localhost','localhost.%',socket.gethostname(),socket.getfqdn()] - + mysql_proc = subprocess.Popen( + mysql_cmd, shell=True, stdin=subprocess.PIPE) + hosts = ['localhost', 'localhost.%', + socket.gethostname(), socket.getfqdn()] + if options.voms_host: - hosts = [options.voms_host,options.voms_host + '.%'] - + hosts = [options.voms_host, options.voms_host + '.%'] + for host in hosts: print >>mysql_proc.stdin, "grant select on %s.* to '%s'@'%s' identified by '%s';" % (options.dbname, options.username, @@ -180,55 +213,63 @@ def grant_ro_access(): print >>mysql_proc.stdin, "flush privileges;" mysql_proc.stdin.close() status = mysql_proc.wait() - + if status != 0: - error_and_exit("Error granting read-only access to user %s on database %s: %s" % (options.username, + error_and_exit("Error granting read-only access to user %s on database %s: %s" % (options.username, options.dbname, mysql_proc.stdout.read())) - -supported_commands = {'create_db': create_db, - 'drop_db': drop_db, - 'grant_rw_access': grant_rw_access, + +supported_commands = {'create_db': create_db, + 'drop_db': drop_db, + 'grant_rw_access': grant_rw_access, 'grant_ro_access': grant_ro_access} -required_options = [ "username", "password", "dbname"] +required_options = ["username", "password", "dbname"] + def check_mysql_command(options): test_cmd = "%s --version" % options.command - proc = subprocess.Popen(test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(test_cmd, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = proc.communicate() - + combined_output = "%s %s" % (out, err) - + status = proc.wait() - + if status != 0: - error_and_exit("Error executing %s: %s. Check your MySQL client installation." % (options.command, combined_output.strip())) - + error_and_exit("Error executing %s: %s. Check your MySQL client installation." % ( + options.command, combined_output.strip())) + + def check_args_and_options(options, args): if len(args) != 1 or args[0] not in supported_commands.keys(): - error_and_exit("Please specify a single command among the following:\n\t%s" % "\n\t".join(supported_commands.keys())) - + error_and_exit("Please specify a single command among the following:\n\t%s" % + "\n\t".join(supported_commands.keys())) + missing_options = [] - + if not options.username: - missing_options.append("--dbusername") + missing_options.append("--dbusername") if not options.password: missing_options.append("--dbpassword") if not options.dbname: missing_options.append("--dbname") - + if len(missing_options) != 0: - error_and_exit("Please specify the following missing options:\n\t%s" % "\n\t".join(missing_options)) - + error_and_exit("Please specify the following missing options:\n\t%s" % + "\n\t".join(missing_options)) + + def main(): setup_cl_options() (options, args) = parser.parse_args() - check_args_and_options(options,args) + check_args_and_options(options, args) check_mysql_command(options) - + supported_commands[args[0]](options) - + + if __name__ == '__main__': - main() \ No newline at end of file + main() From 2a40f112c016b182c6cc2fb756f55881516d5180 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 7 Jan 2020 19:22:39 +0100 Subject: [PATCH 40/63] initial systemd support --- .../resources/systemd/voms-admin.service | 15 +++++++++++++++ voms-admin-server/src/assemble/tarball.xml | 7 +++++++ voms-admin-server/src/config/sysconfig | 7 ++----- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 voms-admin-server/resources/systemd/voms-admin.service diff --git a/voms-admin-server/resources/systemd/voms-admin.service b/voms-admin-server/resources/systemd/voms-admin.service new file mode 100644 index 00000000..8e158864 --- /dev/null +++ b/voms-admin-server/resources/systemd/voms-admin.service @@ -0,0 +1,15 @@ +[Unit] +Description=VOMS Admin service + +[Service] +WorkingDirectory=/var/lib/voms-admin +EnvironmentFile=-/etc/sysconfig/voms-admin +User=voms +Type=simple +ExecStart=/usr/bin/java $VOMS_JAVA_OPTS -cp /usr/share/java/voms-container.jar:$OJDBC_JAR org.italiangrid.voms.container.Container >/var/log/voms-admin/voms-admin.out 2>/var/log/voms-admin/voms-admin.err +ExecStop=/bin/kill -TERM $MAINPID +KillMode=process +SuccessExitStatus=143 + +[Install] +WantedBy=multi-user.target diff --git a/voms-admin-server/src/assemble/tarball.xml b/voms-admin-server/src/assemble/tarball.xml index 3c8dc365..0f20530a 100644 --- a/voms-admin-server/src/assemble/tarball.xml +++ b/voms-admin-server/src/assemble/tarball.xml @@ -200,6 +200,13 @@ 0755 true + + + resources/systemd/voms-admin.service + /usr/lib/systemd/system + 0644 + + src/main/resources/c3p0.properties /var/lib/voms-admin/tools diff --git a/voms-admin-server/src/config/sysconfig b/voms-admin-server/src/config/sysconfig index c3c00b99..12e38052 100644 --- a/voms-admin-server/src/config/sysconfig +++ b/voms-admin-server/src/config/sysconfig @@ -14,8 +14,5 @@ ORACLE_LIBRARY_PATH=${package.oracle_library_path} # Default oracle tnsnames.ora location TNS_ADMIN=${package.tns_admin} -# To debug the service, uncomment the following variable -# VOMS_DEBUG=y - -# Sets the VOMS debug port -# VOMS_DEBUG_PORT=8998 +# VOMS ADMIN JVM options +VOMS_JAVA_OPTS="-Xmx512m -Xms512m" From 32af4d1bc76a38019efa4eb8ae78435c41312c15 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 17 Feb 2020 12:22:53 +0100 Subject: [PATCH 41/63] CENTOS 7 dev environment --- compose/.env | 1 + .../assets/hostcert/star_local_io.cert.pem | 85 ++ compose/assets/hostcert/star_local_io.key.pem | 27 + compose/docker-compose.yml | 83 ++ docker-compose.yml | 159 --- docker/voms-admin-server/build-image.sh | 5 - docker/voms-admin-server/dev/centos6/.env | 1 + .../{ => dev/centos6}/Dockerfile | 0 .../{ => dev/centos6}/setup/configure-vos.sh | 0 .../{ => dev/centos6}/setup/create-schemas.sh | 0 .../centos6}/setup/emi-oracle-11.repo | 0 .../{ => dev/centos6}/setup/load-db-dump.sh | 0 .../{ => dev/centos6}/setup/logback.xml | 0 .../{ => dev/centos6}/setup/orgdb-util.sh | 0 .../{ => dev/centos6}/setup/orgdb.template | 0 .../{ => dev/centos6}/setup/run.sh | 0 .../{ => dev/centos6}/setup/setup-java.sh | 0 .../centos6}/setup/setup-voms-user.sh | 0 .../{ => dev/centos6}/setup/test_0.dump.sql | 0 .../{ => dev/centos6}/setup/tnsnames.ora | 0 .../{ => dev/centos6}/setup/upgrade-db.sh | 0 docker/voms-admin-server/dev/centos7/.env | 1 + .../voms-admin-server/dev/centos7/Dockerfile | 18 + .../dev/centos7/setup/configure-vos.sh | 36 + .../dev/centos7/setup/create-schemas.sh | 25 + .../dev/centos7/setup/load-db-dump.sh | 22 + .../dev/centos7/setup/logback.xml | 32 + .../dev/centos7/setup/orgdb-util.sh | 9 + .../dev/centos7/setup/orgdb.template | 4 + .../dev/centos7/setup/repo/igi-test-ca.repo | 8 + .../dev/centos7/setup/repo/pkg-voms.repo | 8 + .../centos7/setup/repo/voms-externals.repo | 8 + .../dev/centos7/setup/run.sh | 210 ++++ .../dev/centos7/setup/setup-java.sh | 9 + .../dev/centos7/setup/setup-voms-user.sh | 11 + .../dev/centos7/setup/setup.sh | 11 + .../dev/centos7/setup/test_0.dump.sql | 1029 +++++++++++++++++ .../dev/centos7/setup/tnsnames.ora | 21 + .../dev/centos7/setup/upgrade-db.sh | 16 + docker/voms-admin-server/push-image.sh | 15 - 40 files changed, 1675 insertions(+), 179 deletions(-) create mode 100644 compose/.env create mode 100644 compose/assets/hostcert/star_local_io.cert.pem create mode 100644 compose/assets/hostcert/star_local_io.key.pem create mode 100644 compose/docker-compose.yml delete mode 100644 docker-compose.yml delete mode 100755 docker/voms-admin-server/build-image.sh create mode 100644 docker/voms-admin-server/dev/centos6/.env rename docker/voms-admin-server/{ => dev/centos6}/Dockerfile (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/configure-vos.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/create-schemas.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/emi-oracle-11.repo (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/load-db-dump.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/logback.xml (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/orgdb-util.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/orgdb.template (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/run.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/setup-java.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/setup-voms-user.sh (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/test_0.dump.sql (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/tnsnames.ora (100%) rename docker/voms-admin-server/{ => dev/centos6}/setup/upgrade-db.sh (100%) create mode 100644 docker/voms-admin-server/dev/centos7/.env create mode 100644 docker/voms-admin-server/dev/centos7/Dockerfile create mode 100644 docker/voms-admin-server/dev/centos7/setup/configure-vos.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/create-schemas.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/load-db-dump.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/logback.xml create mode 100644 docker/voms-admin-server/dev/centos7/setup/orgdb-util.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/orgdb.template create mode 100644 docker/voms-admin-server/dev/centos7/setup/repo/igi-test-ca.repo create mode 100644 docker/voms-admin-server/dev/centos7/setup/repo/pkg-voms.repo create mode 100644 docker/voms-admin-server/dev/centos7/setup/repo/voms-externals.repo create mode 100755 docker/voms-admin-server/dev/centos7/setup/run.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/setup-java.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/setup-voms-user.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/setup.sh create mode 100644 docker/voms-admin-server/dev/centos7/setup/test_0.dump.sql create mode 100644 docker/voms-admin-server/dev/centos7/setup/tnsnames.ora create mode 100644 docker/voms-admin-server/dev/centos7/setup/upgrade-db.sh delete mode 100755 docker/voms-admin-server/push-image.sh diff --git a/compose/.env b/compose/.env new file mode 100644 index 00000000..d0e93af4 --- /dev/null +++ b/compose/.env @@ -0,0 +1 @@ +COMPOSE_PROJECT_NAME=voms-admin-server diff --git a/compose/assets/hostcert/star_local_io.cert.pem b/compose/assets/hostcert/star_local_io.cert.pem new file mode 100644 index 00000000..f4410372 --- /dev/null +++ b/compose/assets/hostcert/star_local_io.cert.pem @@ -0,0 +1,85 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 784 (0x310) + Signature Algorithm: sha512WithRSAEncryption + Issuer: C=IT, O=IGI, CN=Test CA + Validity + Not Before: Apr 20 09:55:23 2017 GMT + Not After : Apr 18 09:55:23 2027 GMT + Subject: C=IT, O=IGI, CN=*.local.io + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:c6:1c:fa:92:9e:ed:0d:5f:bc:3e:49:5e:90:14: + 02:a7:78:de:b6:cf:57:23:81:4d:7f:81:8e:ae:43: + 67:8b:ff:83:4c:c1:1e:f8:ab:c1:40:d5:72:e4:65: + c8:ff:7b:f7:6c:ac:b4:b7:43:f2:e7:98:b7:c9:76: + 25:8c:e3:81:9a:c4:77:ba:12:f6:47:0e:01:ea:80: + e8:d3:bb:28:7d:b8:1b:f6:dd:51:8c:9e:3f:26:25: + 23:ab:f0:a6:ae:5e:4f:cf:ad:18:3d:cc:b1:2f:91: + 01:84:17:d5:17:44:be:d2:fa:20:0d:ff:87:07:63: + 52:0f:9c:c3:32:62:23:68:9c:e7:40:06:98:65:69: + 11:4b:38:88:0e:8b:7b:fe:23:c4:15:db:ee:f8:a6: + 48:ee:91:89:14:35:5b:6f:f2:85:53:21:62:7b:a5: + 7a:38:53:63:6d:f3:21:bb:9b:18:1e:e4:a0:c0:95: + c0:68:61:75:da:77:00:3a:15:75:42:1d:30:47:58: + 2f:0e:9b:14:06:38:97:03:a3:20:d5:06:e2:70:81: + e3:b5:2a:ac:69:97:dc:87:df:5c:9a:80:c4:2c:36: + 62:75:f3:01:59:5a:2f:56:70:a0:2a:c7:2a:a8:6b: + da:1c:b4:f8:92:d5:11:39:c9:21:30:e9:f1:53:7f: + 34:f5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + E4:A0:F6:A4:A4:4C:AC:A9:C1:2E:42:B3:24:15:B6:4D:EF:7E:F9:52 + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Microsoft Server Gated Crypto, Netscape Server Gated Crypto, E-mail Protection + X509v3 Authority Key Identifier: + keyid:91:77:36:7B:2E:B4:69:F3:27:EA:B7:F6:08:8B:4A:23:A2:11:49:C6 + + X509v3 Subject Alternative Name: + DNS:*.local.io + Signature Algorithm: sha512WithRSAEncryption + f6:3e:b2:2c:23:6c:34:54:2b:68:cb:de:d3:da:68:50:29:92: + 92:39:5e:90:19:9e:c6:08:06:c3:c1:21:24:10:bd:93:a2:28: + 4f:d6:7a:2b:8f:14:0b:86:b6:17:d9:8c:4a:c6:a6:af:10:39: + 66:d6:2c:be:b2:d4:76:19:ab:5a:4c:02:fc:a2:a3:8c:a4:8d: + 85:38:9b:9f:2b:84:4b:ed:c4:ca:a7:f6:bc:53:bb:ef:a2:12: + 75:e5:dd:b1:83:66:ce:91:ff:8d:76:de:3e:e6:9d:26:bd:aa: + f5:a2:23:40:0b:d7:3e:9f:9a:5f:79:df:96:d6:a4:55:86:f5: + f7:9f:86:6b:8d:1b:5b:0d:c0:29:40:84:0a:d7:0b:61:ea:6a: + 40:14:c8:4a:5e:48:7f:5f:4e:ff:32:3e:28:90:b3:11:a1:2b: + 8e:11:5b:ad:86:f4:57:d0:93:6e:91:3b:b0:99:16:46:07:e7: + 7a:df:4c:4e:50:22:03:6f:48:7d:c7:f8:20:9f:2f:dc:58:ed: + d8:84:52:a7:36:e3:84:fa:16:b4:d5:ff:d6:b1:30:66:14:49: + d4:0c:06:ee:74:2f:04:16:a4:ac:08:e3:8f:ed:bc:f4:61:e3: + 73:aa:23:bd:45:82:d6:cc:d3:59:2e:4f:0a:b1:38:d9:b5:ac: + 92:e9:e6:04 +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgICAxAwDQYJKoZIhvcNAQENBQAwLTELMAkGA1UEBhMCSVQx +DDAKBgNVBAoMA0lHSTEQMA4GA1UEAwwHVGVzdCBDQTAeFw0xNzA0MjAwOTU1MjNa +Fw0yNzA0MTgwOTU1MjNaMDAxCzAJBgNVBAYTAklUMQwwCgYDVQQKDANJR0kxEzAR +BgNVBAMMCioubG9jYWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDGHPqSnu0NX7w+SV6QFAKneN62z1cjgU1/gY6uQ2eL/4NMwR74q8FA1XLkZcj/ +e/dsrLS3Q/LnmLfJdiWM44GaxHe6EvZHDgHqgOjTuyh9uBv23VGMnj8mJSOr8Kau +Xk/PrRg9zLEvkQGEF9UXRL7S+iAN/4cHY1IPnMMyYiNonOdABphlaRFLOIgOi3v+ +I8QV2+74pkjukYkUNVtv8oVTIWJ7pXo4U2Nt8yG7mxge5KDAlcBoYXXadwA6FXVC +HTBHWC8OmxQGOJcDoyDVBuJwgeO1Kqxpl9yH31yagMQsNmJ18wFZWi9WcKAqxyqo +a9octPiS1RE5ySEw6fFTfzT1AgMBAAGjgbgwgbUwDAYDVR0TAQH/BAIwADAdBgNV +HQ4EFgQU5KD2pKRMrKnBLkKzJBW2Te9++VIwDgYDVR0PAQH/BAQDAgXgMD4GA1Ud +JQQ3MDUGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQB +BggrBgEFBQcDBDAfBgNVHSMEGDAWgBSRdzZ7LrRp8yfqt/YIi0ojohFJxjAVBgNV +HREEDjAMggoqLmxvY2FsLmlvMA0GCSqGSIb3DQEBDQUAA4IBAQD2PrIsI2w0VCto +y97T2mhQKZKSOV6QGZ7GCAbDwSEkEL2ToihP1norjxQLhrYX2YxKxqavEDlm1iy+ +stR2GataTAL8oqOMpI2FOJufK4RL7cTKp/a8U7vvohJ15d2xg2bOkf+Ndt4+5p0m +var1oiNAC9c+n5pfed+W1qRVhvX3n4ZrjRtbDcApQIQK1wth6mpAFMhKXkh/X07/ +Mj4okLMRoSuOEVuthvRX0JNukTuwmRZGB+d630xOUCIDb0h9x/ggny/cWO3YhFKn +NuOE+ha01f/WsTBmFEnUDAbudC8EFqSsCOOP7bz0YeNzqiO9RYLWzNNZLk8KsTjZ +tayS6eYE +-----END CERTIFICATE----- diff --git a/compose/assets/hostcert/star_local_io.key.pem b/compose/assets/hostcert/star_local_io.key.pem new file mode 100644 index 00000000..e300a071 --- /dev/null +++ b/compose/assets/hostcert/star_local_io.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxhz6kp7tDV+8PklekBQCp3jets9XI4FNf4GOrkNni/+DTMEe ++KvBQNVy5GXI/3v3bKy0t0Py55i3yXYljOOBmsR3uhL2Rw4B6oDo07sofbgb9t1R +jJ4/JiUjq/Cmrl5Pz60YPcyxL5EBhBfVF0S+0vogDf+HB2NSD5zDMmIjaJznQAaY +ZWkRSziIDot7/iPEFdvu+KZI7pGJFDVbb/KFUyFie6V6OFNjbfMhu5sYHuSgwJXA +aGF12ncAOhV1Qh0wR1gvDpsUBjiXA6Mg1QbicIHjtSqsaZfch99cmoDELDZidfMB +WVovVnCgKscqqGvaHLT4ktUROckhMOnxU3809QIDAQABAoIBAENc3yazu07s2okj +UXAUHcLsKm5mme6MrNlKKEXAzZigzPhwQiOz4wY0jdhzc6DLehoNr3UROareFr/9 +2E7LnOoPG9a9U9hdPvGJ26EC5oW48GlEX9I8jKRfxH1WWpa3otOuu6tnymeuGqHb +qK08xtXeDsAzvqoYb3K3jve2vut2tRXniXoTg/Cgns4WF8/LuZBU6L1ocePIX4R0 +2tNX3z7qoQP9Grf1VVhBD08ZODPz7ckaZr6F5vBauHqwn3zR1Ui0xl2hVjxZFcRV +FCTI3ny77kNYk49xWpPBh5vCWTpzC0sbQ7/pcp6swGq7RZBaMerJXi8LjQ5vD95j +54hrrAECgYEA7kP7jLBiPkDgHwNWdGiUy4dbaN3JwKcCKKWuixkI+vrDxQmwuxEn +3yvcsq+7PtSmGnYsV+xn9EXQpqLOitzHsmxta5Yc3v7YRwpjmoJUcRSdAehvC6d4 +QGdSm7v8IraO+9//wqGDnVfHaWAlterRBevkh+kRchC+FYQH5wZfvLUCgYEA1Nvq +Vbe5+BOHhJWDWz3XSL4gSZrqsZaGp19brEPD4DKpzfyR04spV4dDnB+se3EqDkwn +4cmgY1Fy0/IQ5Y3lBbTv1DcywU07QCZXL0Sfv6Snl97xfx77g58xaFmxj4dvLlyG +w84oPotIOCFM2sJLcXlVyEoSVjYXnC2wktJY/0ECgYEAlTy9naSJFIccGjDEAQvU +TxsMFUX97Y5t2rnT9soKhvF0l8D3EmSvfaiChuVtOfCFzcNBCR1JC4aDJyyIhA+/ +gTFK4/1VPhOPsgd+1bNWYrHPmfdVPo550pUk9+iqB7AjJP5ruyPhRTdK7uTLGgPn +Qnc7YCmKxNBZzy4wqPKkGpUCgYAa4TqSYIUngq/WWlsgJosNMJU7Nkj07CFM+YnG +EzilE0DGNmLj5+rslrQ+/vD1FbFN5OgUZzXN1Pc/NI5VrrmBIvw2PFI4ftxAmZbg +7TWPKefQEeNFPlBcqrm+h7UYfu3XWO/bwijq3QPdsrbV2TtVtRDUHiZ6pJIOsuZd +ZBrBAQKBgQDQYb1pe9Fj4ChtWbCGpzb3F5xyErAXiO0stn69PN8wr4JMRNFr71KX +ebzJzW6Q1IE10qhDvCQnX0DD0yqAUtBsCMpN7Pve2xFBHtZLs83Th7kbqJhbeZ1P +DTkDvx0q4GEDtwssm4qIdT01ZY2F+DuDqMuuGDyORDjjUh35vAjw/Q== +-----END RSA PRIVATE KEY----- diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml new file mode 100644 index 00000000..b0d31fd2 --- /dev/null +++ b/compose/docker-compose.yml @@ -0,0 +1,83 @@ +version: '3.5' + +volumes: + trustanchors: + cabundle: + db_data: + +services: + trust: + image: indigoiam/trustanchors + environment: + - FORCE_TRUST_ANCHORS_UPDATE=1 + volumes: + - trustanchors:/etc/grid-security/certificates + - cabundle:/etc/pki + + db: + image: mariadb:latest + container_name: db + ports: + - "3306:3306" + volumes: + - db_data:/var/lib/mysql + + environment: + MYSQL_ROOT_PASSWORD: pwd + MYSQL_USER: voms + MYSQL_PASSWORD: pwd + MYSQL_DATABASE: voms_test + + adminserver: + image: italiangrid/voms-admin-server-dev-centos7:latest + domainname: local.io + depends_on: + - db + + volumes: + - trustanchors:/etc/grid-security/certificates/ + - ./assets/hostcert/star_local_io.cert.pem:/etc/grid-security/hostcert.pem + - ./assets/hostcert/star_local_io.key.pem:/etc/grid-security/hostkey.pem + - ..:/code:ro + - ~/git/orgdb-fake-users/:/orgdb-fake-users:ro + - ~/git/voms-migrate:/migrate:ro + - ~/orgdb:/orgdb:ro + - ~/oracle:/oracle-rpm:ro + + ports: + - "1044:1044" + - "8443:8443" + + environment: + # This is the VOMS Admin configuration + # + VOMS_VO_COUNT: 1 # 0 creates 1 VO, 1 two VOs, ... + VOMS_HOSTNAME: dev.local.io + MAILHOST: mail + MYSQL_ROOT_PASSWORD: pwd + + # VOMS_LOG_LEVEL: debug + VOMS_DEBUG: y + + # Comment the following line to skip tarball installation + #VOMS_DEPLOY_TARBALL: y + + # VOMS_ADMIN_SERVER_PACKAGE_URL: http://ci-01.cnaf.infn.it/download/voms/versions/jenkins-release_voms_packages-13/sl6/x86_64/voms-admin-server-3.5.1-1.el6.centos.noarch.rpm + # VOMS_ADMIN_SERVER_VERSION: 3.3.3 + # VOMS_DEBUG_SUSPEND: y + VOMS_PRE_CONFIGURE: y + # VOMS_SKIP_CONFIGURE: y + VOMS_SKIP_JAVA_SETUP: y + # VOMS_UPGRADE_DB: y + + #VOMS_LOAD_DB_DUMP: y + VOMS_DEV_MODE: y + + VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check + VOMS_ARGS: --war /code/voms-admin-server/target/voms-admin.war + + # ENABLE_YOURKIT: y + # ENABLE_JREBEL: y + # ENABLE_JMX: y + # HIBERNATE_LOG_LEVEL: DEBUG + # STRUTS_LOG_LEVEL: DEBUG diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index d1d5e468..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,159 +0,0 @@ -version: '2' - -services: - - data: - image: busybox - volumes: - - /var/lib/mysql - command: /bin/true - - db: - image: mariadb:latest - container_name: db - ports: - - "3306:3306" - volumes_from: - - data - - environment: - MYSQL_ROOT_PASSWORD: pwd - MYSQL_USER: voms - MYSQL_PASSWORD: pwd - MYSQL_DATABASE: voms_test - - mail: - image: jlynn/python-smtp - ports: - - "25:25" - - adminserver: - image: italiangrid/voms-admin-server:latest - domainname: local.io - - volumes: - - /etc/voms - - /etc/grid-security - - .:/code:ro - - ~/.jrebel:/home/voms/.jrebel:rw - - ~/jrebel:/jrebel:ro - - ~/yourkit:/yourkit:ro - - ~/git/voms-admin-server/docker/voms-admin-server/setup:/scripts:ro - - ~/git/orgdb-fake-users/:/orgdb-fake-users:ro - - ~/git/voms-migrate:/migrate:ro - - ~/orgdb:/orgdb:ro - - ports: - # 20001 is the default yourkit port - # - "20001:20001" - # 6002 is the default JMX port used when enabling JMX - # - "6002:6002" - # 1044 is the debug port - - "1044:1044" - - "8443:8443" - - links: - - db - - mail - - environment: - # This is need for haproxy to properly load balance stuff... - TCP_PORTS: 8443 - - # This is the VOMS Admin configuration - # - VOMS_VO_COUNT: 1 # 0 creates 1 VO, 1 two VOs, ... - VOMS_HOSTNAME: dev.local.io - MAILHOST: mail - MYSQL_ROOT_PASSWORD: pwd - - # VOMS_LOG_LEVEL: debug - VOMS_DEBUG: y - - # Comment the following line to skip tarball installation - VOMS_DEPLOY_TARBALL: y - - # VOMS_ADMIN_SERVER_PACKAGE_URL: http://ci-01.cnaf.infn.it/download/voms/versions/jenkins-release_voms_packages-13/sl6/x86_64/voms-admin-server-3.5.1-1.el6.centos.noarch.rpm - # VOMS_ADMIN_SERVER_VERSION: 3.3.3 - # VOMS_DEBUG_SUSPEND: y - VOMS_PRE_CONFIGURE: y - # VOMS_SKIP_CONFIGURE: y - VOMS_UPGRADE_DB: y - - #VOMS_LOAD_DB_DUMP: y - VOMS_DEV_MODE: y - - VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check - VOMS_ARGS: --war /code/voms-admin-server/target/voms-admin.war - - # ENABLE_YOURKIT: y - # ENABLE_JREBEL: y - # ENABLE_JMX: y - # HIBERNATE_LOG_LEVEL: DEBUG - # STRUTS_LOG_LEVEL: DEBUG - - extra_hosts: - - "voms.local.io:192.168.99.101" - - voms: - image: italiangrid/voms-dev:centos6 - domainname: local.io - - depends_on: - - db - - adminserver - - lb - - cap_add: - # The capability below is useful to - # run gdb - - SYS_PTRACE - - volumes: - - $HOME/git/voms-giaco:/voms:ro - - $HOME/git/voms-mysql-plugin:/voms-mysql-plugin:ro - - volumes_from: - - adminserver - - ports: - - "15000:15000" - - links: - - db - - tty: true - - environment: - # Uncomment to build VOMS from sources - # inside the container - VOMS_BUILD_FROM_SOURCES: y - - VOMS_GIT_REPO: file:///voms - VOMS_GIT_BRANCH: ssl11-andrea - - # Uncomment to build voms-mysql-plugin from - # source inside the container - VOMS_BUILD_MYSQL_PLUGIN: y - VOMS_MYSQL_GIT_REPO: file:///voms-mysql-plugin - - VOMS_MYSQL_GIT_BRANCH: fix/VOMS-748 - - lb: - image: dockercloud/haproxy:latest - ports: - - "8443:8443" - - "1936:1936" - - environment: - - MODE=tcp - # - DOCKER_TLS_VERIFY - # - DOCKER_HOST - # - DOCKER_CERT_PATH - - volumes: - # - $DOCKER_CERT_PATH:$DOCKER_CERT_PATH - - /var/run/docker.sock:/var/run/docker.sock - - links: - - adminserver diff --git a/docker/voms-admin-server/build-image.sh b/docker/voms-admin-server/build-image.sh deleted file mode 100755 index 551d5aa0..00000000 --- a/docker/voms-admin-server/build-image.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-server-dev"} - -docker build --no-cache=true -t ${VOMS_ADMIN_SERVER_IMAGE} . diff --git a/docker/voms-admin-server/dev/centos6/.env b/docker/voms-admin-server/dev/centos6/.env new file mode 100644 index 00000000..f77df07b --- /dev/null +++ b/docker/voms-admin-server/dev/centos6/.env @@ -0,0 +1 @@ +DOCKER_IMAGE=italiangrid/voms-admin-server-dev-centos6 diff --git a/docker/voms-admin-server/Dockerfile b/docker/voms-admin-server/dev/centos6/Dockerfile similarity index 100% rename from docker/voms-admin-server/Dockerfile rename to docker/voms-admin-server/dev/centos6/Dockerfile diff --git a/docker/voms-admin-server/setup/configure-vos.sh b/docker/voms-admin-server/dev/centos6/setup/configure-vos.sh similarity index 100% rename from docker/voms-admin-server/setup/configure-vos.sh rename to docker/voms-admin-server/dev/centos6/setup/configure-vos.sh diff --git a/docker/voms-admin-server/setup/create-schemas.sh b/docker/voms-admin-server/dev/centos6/setup/create-schemas.sh similarity index 100% rename from docker/voms-admin-server/setup/create-schemas.sh rename to docker/voms-admin-server/dev/centos6/setup/create-schemas.sh diff --git a/docker/voms-admin-server/setup/emi-oracle-11.repo b/docker/voms-admin-server/dev/centos6/setup/emi-oracle-11.repo similarity index 100% rename from docker/voms-admin-server/setup/emi-oracle-11.repo rename to docker/voms-admin-server/dev/centos6/setup/emi-oracle-11.repo diff --git a/docker/voms-admin-server/setup/load-db-dump.sh b/docker/voms-admin-server/dev/centos6/setup/load-db-dump.sh similarity index 100% rename from docker/voms-admin-server/setup/load-db-dump.sh rename to docker/voms-admin-server/dev/centos6/setup/load-db-dump.sh diff --git a/docker/voms-admin-server/setup/logback.xml b/docker/voms-admin-server/dev/centos6/setup/logback.xml similarity index 100% rename from docker/voms-admin-server/setup/logback.xml rename to docker/voms-admin-server/dev/centos6/setup/logback.xml diff --git a/docker/voms-admin-server/setup/orgdb-util.sh b/docker/voms-admin-server/dev/centos6/setup/orgdb-util.sh similarity index 100% rename from docker/voms-admin-server/setup/orgdb-util.sh rename to docker/voms-admin-server/dev/centos6/setup/orgdb-util.sh diff --git a/docker/voms-admin-server/setup/orgdb.template b/docker/voms-admin-server/dev/centos6/setup/orgdb.template similarity index 100% rename from docker/voms-admin-server/setup/orgdb.template rename to docker/voms-admin-server/dev/centos6/setup/orgdb.template diff --git a/docker/voms-admin-server/setup/run.sh b/docker/voms-admin-server/dev/centos6/setup/run.sh similarity index 100% rename from docker/voms-admin-server/setup/run.sh rename to docker/voms-admin-server/dev/centos6/setup/run.sh diff --git a/docker/voms-admin-server/setup/setup-java.sh b/docker/voms-admin-server/dev/centos6/setup/setup-java.sh similarity index 100% rename from docker/voms-admin-server/setup/setup-java.sh rename to docker/voms-admin-server/dev/centos6/setup/setup-java.sh diff --git a/docker/voms-admin-server/setup/setup-voms-user.sh b/docker/voms-admin-server/dev/centos6/setup/setup-voms-user.sh similarity index 100% rename from docker/voms-admin-server/setup/setup-voms-user.sh rename to docker/voms-admin-server/dev/centos6/setup/setup-voms-user.sh diff --git a/docker/voms-admin-server/setup/test_0.dump.sql b/docker/voms-admin-server/dev/centos6/setup/test_0.dump.sql similarity index 100% rename from docker/voms-admin-server/setup/test_0.dump.sql rename to docker/voms-admin-server/dev/centos6/setup/test_0.dump.sql diff --git a/docker/voms-admin-server/setup/tnsnames.ora b/docker/voms-admin-server/dev/centos6/setup/tnsnames.ora similarity index 100% rename from docker/voms-admin-server/setup/tnsnames.ora rename to docker/voms-admin-server/dev/centos6/setup/tnsnames.ora diff --git a/docker/voms-admin-server/setup/upgrade-db.sh b/docker/voms-admin-server/dev/centos6/setup/upgrade-db.sh similarity index 100% rename from docker/voms-admin-server/setup/upgrade-db.sh rename to docker/voms-admin-server/dev/centos6/setup/upgrade-db.sh diff --git a/docker/voms-admin-server/dev/centos7/.env b/docker/voms-admin-server/dev/centos7/.env new file mode 100644 index 00000000..16064204 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/.env @@ -0,0 +1 @@ +DOCKER_IMAGE=italiangrid/voms-admin-server-dev-centos7 diff --git a/docker/voms-admin-server/dev/centos7/Dockerfile b/docker/voms-admin-server/dev/centos7/Dockerfile new file mode 100644 index 00000000..881aaaa7 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/Dockerfile @@ -0,0 +1,18 @@ +FROM centos:7 + +ENV VOMS_DB_USERNAME voms +ENV VOMS_DB_PASSWORD pwd +ENV VOMS_DB_NAME voms_test +ENV VOMS_MAIL_FROM voms-admin@dev.local.io +ENV VOMS_HOSTNAME dev.local.io + +ADD setup /scripts +ADD setup/repo/*.repo /etc/yum.repos.d/ + +RUN chmod +x /scripts/run.sh +RUN yum -y install sudo && sh /scripts/setup-voms-user.sh && sh /scripts/setup.sh + +VOLUME /var/log/voms-admin +CMD /scripts/run.sh + +EXPOSE 8443 1044 diff --git a/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh b/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh new file mode 100644 index 00000000..4b8914ab --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -ex + +VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} +VO_COUNT=${VOMS_VO_COUNT:-1} +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} +VOMS_SMTP_HOST=${VOMS_SMTP_HOST:-mail} +BASE_CORE_PORT=${VOMS_BASE_CORE_PORT:-15000} + +configure_vo(){ + + VO_NAME=${VO_NAME_PREFIX}_$1 + voms-configure install \ + --vo ${VO_NAME} \ + --dbtype mysql \ + --deploy-database \ + --dbname ${VO_NAME} \ + --dbusername $VOMS_DB_USERNAME \ + --dbpassword $VOMS_DB_PASSWORD \ + --dbhost ${VOMS_MYSQL_HOST} \ + --mail-from $VOMS_MAIL_FROM \ + --smtp-host ${VOMS_SMTP_HOST} \ + --membership-check-period 60 \ + --hostname ${VOMS_HOSTNAME} \ + --core-port $((${BASE_CORE_PORT}+$1)) \ + ${CONFIGURE_VO_OPTIONS} +} + +for i in $(seq 0 ${VO_COUNT}); do + configure_vo $i +done + +if [[ -f "/etc/voms-admin/voms-admin-server.properties" ]]; then + sed -i -e "s#localhost#${VOMS_HOSTNAME}#g" \ + /etc/voms-admin/voms-admin-server.properties +fi diff --git a/docker/voms-admin-server/dev/centos7/setup/create-schemas.sh b/docker/voms-admin-server/dev/centos7/setup/create-schemas.sh new file mode 100644 index 00000000..06c3e173 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/create-schemas.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -x + +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} + +VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} +VO_COUNT=${VOMS_VO_COUNT:-1} + +create_vo_schema(){ + + tmp_file=$(mktemp /tmp/create-schema-$1-XXX.sql) + + cat << EOF > ${tmp_file} + CREATE DATABASE IF NOT EXISTS test_$1; + GRANT ALL ON test_$1.* TO '${VOMS_DB_USERNAME}'@'%' IDENTIFIED BY '${VOMS_DB_PASSWORD}'; +EOF + + cat ${tmp_file} + cat ${tmp_file} | mysql -h${VOMS_MYSQL_HOST} -uroot -p${MYSQL_ROOT_PASSWORD} +} + + +for i in $(seq 0 ${VO_COUNT}); do + create_vo_schema $i; +done diff --git a/docker/voms-admin-server/dev/centos7/setup/load-db-dump.sh b/docker/voms-admin-server/dev/centos7/setup/load-db-dump.sh new file mode 100644 index 00000000..aa8c9cb7 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/load-db-dump.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -ex + +SCRIPTS_PREFIX=${SCRIPTS_PREFIX:-/scripts} +VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} +VO_COUNT=${VOMS_VO_COUNT:-1} + +load_db_dump(){ + + VO_NAME=${VO_NAME_PREFIX}_$1 + dump_file=${VO_NAME}.dump.sql + if [[ -f ${SCRIPTS_PREFIX}/${dump_file} ]]; then + echo "Loading dump file ${SCRIPTS_PREFIX}/${dump_file} for VO ${VO_NAME}" + cat ${SCRIPTS_PREFIX}/${dump_file} | mysql -hdb -u${VOMS_DB_USERNAME} -p${VOMS_DB_PASSWORD} ${VO_NAME} + else + echo "${dump_file} not found" + fi +} + +for i in $(seq 0 ${VO_COUNT}); do + load_db_dump $i +done diff --git a/docker/voms-admin-server/dev/centos7/setup/logback.xml b/docker/voms-admin-server/dev/centos7/setup/logback.xml new file mode 100644 index 00000000..e78e45cd --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/logback.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + %date{yyyy-MM-dd HH:mm:ss.SSS'Z',UTC} - [%contextName] %level [%thread] [%logger{0}] - %msg%n + + + + + + + + diff --git a/docker/voms-admin-server/dev/centos7/setup/orgdb-util.sh b/docker/voms-admin-server/dev/centos7/setup/orgdb-util.sh new file mode 100644 index 00000000..78346cf2 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/orgdb-util.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -ex + +source /etc/sysconfig/voms-admin + +OJDBC_JAR=${OJDBC_JAR:-${ORACLE_LIBRARY_PATH}/ojdbc6.jar} +ORACLE_ENV="LD_LIBRARY_PATH=$ORACLE_LIBRARY_PATH TNS_ADMIN=$TNS_ADMIN" + +TNS_ADMIN=/home/voms LD_LIBRARY_PATH=${ORACLE_LIBRARY_PATH} java -cp ${OJDBC_JAR}:'/var/lib/voms-admin/lib/*':/usr/share/java/voms-admin.jar org.glite.security.voms.admin.integration.orgdb.tools.OrgDBUtil -c /etc/voms-admin/test_0/orgdb.properties $@ diff --git a/docker/voms-admin-server/dev/centos7/setup/orgdb.template b/docker/voms-admin-server/dev/centos7/setup/orgdb.template new file mode 100644 index 00000000..ceb4f281 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/orgdb.template @@ -0,0 +1,4 @@ +voms.external-validators = orgdb +voms.ext.orgdb.configClass = org.glite.security.voms.admin.integration.orgdb.OrgDBConfigurator +voms.ext.orgdb.experimentName = ATLAS +voms.ext.orgdb.membership_check.period = 30 diff --git a/docker/voms-admin-server/dev/centos7/setup/repo/igi-test-ca.repo b/docker/voms-admin-server/dev/centos7/setup/repo/igi-test-ca.repo new file mode 100644 index 00000000..0710cdde --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/repo/igi-test-ca.repo @@ -0,0 +1,8 @@ +[Test-CA] +name=Test-CA +baseurl=https://ci.cloud.cnaf.infn.it/job/repo_test_ca/lastSuccessfulBuild/artifact/yum/ +protect=1 +enabled=1 +priority=1 +gpgcheck=0 +sslverify=0 diff --git a/docker/voms-admin-server/dev/centos7/setup/repo/pkg-voms.repo b/docker/voms-admin-server/dev/centos7/setup/repo/pkg-voms.repo new file mode 100644 index 00000000..ba5168f7 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/repo/pkg-voms.repo @@ -0,0 +1,8 @@ +[pkg-VOMS] +name=pkg-VOMS +baseurl=https://ci.cloud.cnaf.infn.it/job/pkg.voms/job/v0120.01/lastSuccessfulBuild/artifact/artifacts/stage-area/centos7 +protect=1 +enabled=1 +priority=1 +gpgcheck=0 +sslverify=1 diff --git a/docker/voms-admin-server/dev/centos7/setup/repo/voms-externals.repo b/docker/voms-admin-server/dev/centos7/setup/repo/voms-externals.repo new file mode 100644 index 00000000..3721a0bb --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/repo/voms-externals.repo @@ -0,0 +1,8 @@ +[voms-externals] +name=voms-externals +baseurl=https://repo.cloud.cnaf.infn.it/repository/voms-externals-rpm/centos7 +protect=1 +enabled=1 +priority=1 +gpgcheck=0 +sslverify=1 diff --git a/docker/voms-admin-server/dev/centos7/setup/run.sh b/docker/voms-admin-server/dev/centos7/setup/run.sh new file mode 100755 index 00000000..d1c95a2d --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/run.sh @@ -0,0 +1,210 @@ +#!/bin/bash +set -ex + +SCRIPTS_PREFIX=${SCRIPTS_PREFIX:-/scripts} +VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} +VO_COUNT=${VOMS_VO_COUNT:-1} + +VOMS_BASE_CORE_PORT=${VOMS_BASE_CORE_PORT:-15000} +VOMS_MYSQL_HOST=${VOMS_MYSQL_HOST:-db} +VOMS_MYSQL_PORT=${VOMS_MYSQL_PORT:-3306} + +# Wait for database service to be up +mysql_host=${VOMS_MYSQL_HOST} +mysql_port=${VOMS_MYSQL_PORT} + +echo -n "waiting for TCP connection to $mysql_host:$mysql_port..." + + +while ! nc -w 1 $mysql_host $mysql_port 2>/dev/null +do + echo -n . + sleep 1 +done + +echo 'Database server is up.' + +## Create database schemas +/bin/bash ${SCRIPTS_PREFIX}/create-schemas.sh + +if [[ -n "${VOMS_ADMIN_SERVER_PACKAGE_URL}" ]]; then + yum -y remove voms-admin-server + yum -y install ${VOMS_ADMIN_SERVER_PACKAGE_URL} +fi + +# Install requested voms-admin-server version +if [[ -n "${VOMS_ADMIN_SERVER_VERSION}" ]]; then + yum -y remove voms-admin-server + yum install -y voms-admin-server-${VOMS_ADMIN_SERVER_VERSION} +fi + +# Install requested voms-admin client +if [[ -n "${VOMS_ADMIN_CLIENT_VERSION}" ]]; then + yum -y remove voms-admin-client + yum install -y voms-admin-client-${VOMS_ADMIN_CLIENT_VERSION} +fi + +cp ${SCRIPTS_PREFIX}/tnsnames.ora /home/voms +chown voms:voms /home/voms/tnsnames.ora + +## Setup certificates +VOMS_X509_CERT=${VOMS_X509_CERT:-/etc/grid-security/hostcert.pem} +VOMS_X509_KEY=${VOMS_X509_KEY:-/etc/grid-security/hostkey.pem} + +cp ${VOMS_X509_CERT} /etc/grid-security/vomscert.pem +cp ${VOMS_X509_KEY} /etc/grid-security/vomskey.pem +chown voms:voms /etc/grid-security/voms*.pem + +# Do this or voms-admin webapp will fail silently and always return 503 +mkdir -p /etc/grid-security/vomsdir + +## Preconfigure using existing package, if requested, or if just skipping +## the deployment of a tarball +if [[ -z ${VOMS_DEPLOY_TARBALL} ]]; then + VOMS_PRE_CONFIGURE=y +fi + +if [[ -n ${VOMS_LOAD_DB_DUMP} ]]; then + /bin/bash ${SCRIPTS_PREFIX}/load-db-dump.sh +fi + +if [[ -n ${VOMS_PRE_CONFIGURE} ]]; then + echo "Running preconfiguration..." + CONFIGURE_VO_OPTIONS=${VOMS_PRE_CONFIGURE_OPTIONS} /bin/bash ${SCRIPTS_PREFIX}/configure-vos.sh +fi + +if [[ -n "${VOMS_DEPLOY_TARBALL}" ]]; then + echo "Istalling VOMS development tarball from /code" + + ## Install new code + ls -l /code + + old_jars=$(ls /var/lib/voms-admin/lib/*.jar) + for j in ${old_jars}; do + echo "Removing: $j" && rm -rf $j + done + + old_jars=$(ls /var/lib/voms-admin/lib/) + echo "Old jars after removal: ${old_jars}" + + tar -C / -xvzf /code/voms-admin-server/target/voms-admin-server.tar.gz + + chown -R voms:voms /var/lib/voms-admin/work /var/log/voms-admin + + if [[ -n "$VOMS_UPGRADE_DB" ]]; then + echo "Running database upgrade..." + /bin/bash ${SCRIPTS_PREFIX}/upgrade-db.sh + fi + + skip_configuration=false + + ## Skip configuration if requested + [ -n "$VOMS_SKIP_CONFIGURE" ] && skip_configuration=true + + ## But only if configuration for the VO exists + for i in $(seq 0 ${VO_CONT}); do + VO_NAME=${VO_NAME_PREFIX}_$i + [ ! -e "/etc/voms-admin/${VO_NAME}/service.properties" ] && skip_configuration=false + done + + if [[ "$skip_configuration" = "false" ]]; then + echo "Running configuration..." + CONFIGURE_VO_OPTIONS=${VOMS_CONFIGURE_OPTIONS} /bin/bash ${SCRIPTS_PREFIX}/configure-vos.sh + fi +fi + +# Setup logging so that everything goes to stdout +cp ${SCRIPTS_PREFIX}/logback.xml /etc/voms-admin/voms-admin-server.logback + +for i in $(seq 0 ${VO_COUNT}); do + VO_NAME=${VO_NAME_PREFIX}_$i + cp ${SCRIPTS_PREFIX}/logback.xml /etc/voms-admin/${VO_NAME}/logback.xml + chown voms:voms /etc/voms-admin/${VO_NAME}/logback.xml +done + +chown voms:voms /etc/voms-admin/voms-admin-server.logback + +# Setup orgdb.properties, if the orgdb volume is mounted, only for the +# first configured VO +if [ -e "/orgdb/orgdb.properties" ]; then + cp /orgdb/orgdb.properties /etc/voms-admin/test_0/orgdb.properties + chown voms:voms /etc/voms-admin/test_0/orgdb.properties + + # Just a newline + echo >> /etc/voms-admin/test_0/service.properties + cat ${SCRIPTS_PREFIX}/orgdb.template >> /etc/voms-admin/test_0/service.properties +fi + +# Deploy test vos +for i in $(seq 0 ${VO_COUNT}); do + VO_NAME=${VO_NAME_PREFIX}_$i + touch "/var/lib/voms-admin/vo.d/$VO_NAME" +done + +# Set log levels +VOMS_LOG_LEVEL=${VOMS_LOG_LEVEL:-INFO} +JAVA_LOG_LEVEL=${JAVA_LOG_LEVEL:-ERROR} + +VOMS_JAVA_OPTS="-Dvoms.dev=true -DVOMS_LOG_LEVEL=${VOMS_LOG_LEVEL} -DJAVA_LOG_LEVEL=${JAVA_LOG_LEVEL} ${VOMS_JAVA_OPTS}" + +if [ -n "$ENABLE_YOUR_KIT" ]; then + YOUR_KIT_OPTS=${VOMS_YOUR_KIT_OPTS:-"-javaagent:/yourkit/libyjpagent.so,delay=10000,port=20001"} + VOMS_JAVA_OPTS="${VOMS_YOUR_KIT_OPTS} ${VOMS_JAVA_OPTS}" +fi + +if [ -n "$ENABLE_JREBEL" ]; then + if [ -n "$ENABLE_YOUR_KIT" ]; then + echo "YourKit is enabled... will ignore Jrebel" + else + JREBEL_OPTS=${VOMS_JREBEL_OPTS:-"-javaagent:/jrebel/jrebel.jar -Drebel.stats=false -Drebel.usage_reporting=false -Drebel.struts2_plugin=true -Drebel.tiles2_plugin=true"} + VOMS_JAVA_OPTS="${JREBEL_OPTS} ${VOMS_JAVA_OPTS}" + fi +fi + +if [ -z "$VOMS_DEBUG_PORT" ]; then + VOMS_DEBUG_PORT=1044 +fi + +if [ -z "$VOMS_DEBUG_SUSPEND" ]; then + VOMS_DEBUG_SUSPEND="n" +fi + +if [ ! -z "$VOMS_DEBUG" ]; then + VOMS_JAVA_OPTS="-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=$VOMS_DEBUG_PORT,suspend=$VOMS_DEBUG_SUSPEND $VOMS_JAVA_OPTS" +fi + +if [ -n "$ENABLE_JMX" ]; then + JMX_PORT=${VOMS_JMX_PORT:-6002} + VOMS_JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=${JMX_PORT} -Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT} -Djava.rmi.server.hostname=dev.local.io -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false $VOMS_JAVA_OPTS" +fi + +VOMS_JAR=${VOMS_JAR:-/usr/share/java/voms-container.jar} +VOMS_MAIN_CLASS=${VOMS_MAIN_CLASS:-org.italiangrid.voms.container.Container} +ORACLE_LIBRARY_PATH=${ORACLE_LIBRARY_PATH:-/usr/lib64/oracle/11.2.0.3.0/client/lib64} +OJDBC_JAR=${OJDBC_JAR:-${ORACLE_LIBRARY_PATH}/ojdbc6.jar} +TNS_ADMIN=${TNS_ADMIN:-/home/voms} + +ORACLE_ENV="LD_LIBRARY_PATH=$ORACLE_LIBRARY_PATH TNS_ADMIN=$TNS_ADMIN" + +if [ -z "$VOMS_SKIP_JAVA_SETUP" ]; then + /bin/bash ${SCRIPTS_PREFIX}/setup-java.sh +fi + +java -version + +## Add test0 admin +for i in $(seq 0 ${VO_COUNT}); do + VO_NAME=${VO_NAME_PREFIX}_$i + voms-db-util add-admin --vo ${VO_NAME} \ + --cert /usr/share/igi-test-ca/test0.cert.pem \ + || echo "Error creating test0 admin. Does it already exist?" +done + +# Start service +if [ -n "$VOMS_DEV_MODE" ]; then + echo "su voms -s /bin/bash -c \"$ORACLE_ENV java $VOMS_JAVA_OPTS -cp $VOMS_JAR:$OJDBC_JAR $VOMS_MAIN_CLASS $VOMS_ARGS\"" > /root/start-voms-admin.sh + echo "VOMS Admin startup command saved in /root/start-voms-admin.sh . User docker exec to enter this container and start/stop the service as you like" + sleep infinity +else + su voms -s /bin/bash -c "$ORACLE_ENV java $VOMS_JAVA_OPTS -cp $VOMS_JAR:$OJDBC_JAR $VOMS_MAIN_CLASS $VOMS_ARGS" +fi diff --git a/docker/voms-admin-server/dev/centos7/setup/setup-java.sh b/docker/voms-admin-server/dev/centos7/setup/setup-java.sh new file mode 100644 index 00000000..529edc51 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/setup-java.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +JRE_HOME=${JRE_HOME:-/usr/lib/jvm/jre-1.8.0-openjdk.x86_64} +JDK_HOME=${JDK_HOME:-/usr/lib/jvm/java-1.8.0-openjdk.x86_64} + +update-alternatives --set java ${JRE_HOME}/bin/java +update-alternatives --set javac ${JDK_HOME}/bin/javac diff --git a/docker/voms-admin-server/dev/centos7/setup/setup-voms-user.sh b/docker/voms-admin-server/dev/centos7/setup/setup-voms-user.sh new file mode 100644 index 00000000..9904909a --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/setup-voms-user.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex + +VOMS_USER=${VOMS_USER:-voms} +VOMS_USER_UID=${VOMS_USER_UID:-1234} +VOMS_USER_HOME=${VOMS_USER_HOME:-/home/${VOMS_USER}} + +# Add voms user to the sudoers +echo '%wheel ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers +adduser --uid ${VOMS_USER_UID} ${VOMS_USER} +usermod -a -G wheel ${VOMS_USER} diff --git a/docker/voms-admin-server/dev/centos7/setup/setup.sh b/docker/voms-admin-server/dev/centos7/setup/setup.sh new file mode 100644 index 00000000..2e74b209 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/setup.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex + +UMD_REPO_RPM_URL="http://repository.egi.eu/sw/production/umd/4/centos7/x86_64/updates/umd-release-4.1.3-1.el7.centos.noarch.rpm" + +yum clean all +yum install -y hostname epel-release +yum -y install ${UMD_REPO_RPM_URL} +yum -y update +yum -y install openssl java-1.8.0-openjdk-devel nc mysql voms-admin-server voms-admin-client igi-test-ca + diff --git a/docker/voms-admin-server/dev/centos7/setup/test_0.dump.sql b/docker/voms-admin-server/dev/centos7/setup/test_0.dump.sql new file mode 100644 index 00000000..daf148e6 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/test_0.dump.sql @@ -0,0 +1,1029 @@ +-- MySQL dump 10.13 Distrib 5.1.73, for redhat-linux-gnu (x86_64) +-- +-- Host: db Database: test_0 +-- ------------------------------------------------------ +-- Server version 5.5.5-10.1.20-MariaDB-1~jessie + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `acl2` +-- + +DROP TABLE IF EXISTS `acl2`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `acl2` ( + `acl_id` bigint(20) NOT NULL AUTO_INCREMENT, + `group_id` bigint(20) NOT NULL, + `defaultACL` bit(1) NOT NULL, + `role_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`acl_id`), + UNIQUE KEY `group_id` (`group_id`,`defaultACL`,`role_id`), + KEY `FK2D98E8FCFA8B04` (`group_id`), + KEY `FK2D98E8720C9B10` (`role_id`), + CONSTRAINT `FK2D98E8720C9B10` FOREIGN KEY (`role_id`) REFERENCES `roles` (`rid`) ON DELETE CASCADE, + CONSTRAINT `FK2D98E8FCFA8B04` FOREIGN KEY (`group_id`) REFERENCES `groups` (`gid`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=441 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `acl2` +-- + +LOCK TABLES `acl2` WRITE; +/*!40000 ALTER TABLE `acl2` DISABLE KEYS */; +INSERT INTO `acl2` VALUES (1,1,'\0',NULL),(2,1,'\0',1),(100,1,'\0',2),(138,1,'\0',3),(176,1,'\0',4),(215,1,'\0',5),(246,1,'\0',6),(285,1,'\0',7),(325,1,'\0',8),(363,1,'\0',9),(404,1,'\0',10),(3,2,'\0',NULL),(4,2,'\0',1),(98,2,'\0',2),(139,2,'\0',3),(162,2,'\0',4),(204,2,'\0',5),(244,2,'\0',6),(286,2,'\0',7),(321,2,'\0',8),(361,2,'\0',9),(402,2,'\0',10),(5,3,'\0',NULL),(6,3,'\0',1),(120,3,'\0',2),(158,3,'\0',3),(198,3,'\0',4),(238,3,'\0',5),(278,3,'\0',6),(304,3,'\0',7),(346,3,'\0',8),(385,3,'\0',9),(425,3,'\0',10),(7,4,'\0',NULL),(8,4,'\0',1),(101,4,'\0',2),(141,4,'\0',3),(181,4,'\0',4),(221,4,'\0',5),(258,4,'\0',6),(298,4,'\0',7),(340,4,'\0',8),(380,4,'\0',9),(405,4,'\0',10),(9,5,'\0',NULL),(10,5,'\0',1),(113,5,'\0',2),(154,5,'\0',3),(195,5,'\0',4),(239,5,'\0',5),(279,5,'\0',6),(319,5,'\0',7),(360,5,'\0',8),(397,5,'\0',9),(436,5,'\0',10),(11,6,'\0',NULL),(12,6,'\0',1),(95,6,'\0',2),(135,6,'\0',3),(172,6,'\0',4),(210,6,'\0',5),(254,6,'\0',6),(295,6,'\0',7),(342,6,'\0',8),(381,6,'\0',9),(421,6,'\0',10),(13,7,'\0',NULL),(14,7,'\0',1),(88,7,'\0',2),(156,7,'\0',3),(196,7,'\0',4),(235,7,'\0',5),(276,7,'\0',6),(312,7,'\0',7),(351,7,'\0',8),(393,7,'\0',9),(433,7,'\0',10),(15,8,'\0',NULL),(16,8,'\0',1),(109,8,'\0',2),(147,8,'\0',3),(189,8,'\0',4),(228,8,'\0',5),(256,8,'\0',6),(296,8,'\0',7),(336,8,'\0',8),(377,8,'\0',9),(413,8,'\0',10),(17,9,'\0',NULL),(18,9,'\0',1),(89,9,'\0',2),(128,9,'\0',3),(171,9,'\0',4),(206,9,'\0',5),(247,9,'\0',6),(290,9,'\0',7),(330,9,'\0',8),(395,9,'\0',9),(434,9,'\0',10),(19,10,'\0',NULL),(20,10,'\0',1),(106,10,'\0',2),(145,10,'\0',3),(191,10,'\0',4),(229,10,'\0',5),(269,10,'\0',6),(311,10,'\0',7),(347,10,'\0',8),(386,10,'\0',9),(428,10,'\0',10),(21,11,'\0',NULL),(22,11,'\0',1),(91,11,'\0',2),(131,11,'\0',3),(179,11,'\0',4),(219,11,'\0',5),(261,11,'\0',6),(301,11,'\0',7),(338,11,'\0',8),(378,11,'\0',9),(417,11,'\0',10),(23,12,'\0',NULL),(24,12,'\0',1),(116,12,'\0',2),(152,12,'\0',3),(193,12,'\0',4),(231,12,'\0',5),(272,12,'\0',6),(317,12,'\0',7),(358,12,'\0',8),(399,12,'\0',9),(439,12,'\0',10),(25,13,'\0',NULL),(26,13,'\0',1),(93,13,'\0',2),(133,13,'\0',3),(174,13,'\0',4),(213,13,'\0',5),(252,13,'\0',6),(293,13,'\0',7),(332,13,'\0',8),(373,13,'\0',9),(419,13,'\0',10),(27,14,'\0',NULL),(28,14,'\0',1),(86,14,'\0',2),(124,14,'\0',3),(167,14,'\0',4),(233,14,'\0',5),(274,14,'\0',6),(314,14,'\0',7),(354,14,'\0',8),(391,14,'\0',9),(431,14,'\0',10),(29,15,'\0',NULL),(30,15,'\0',1),(111,15,'\0',2),(150,15,'\0',3),(187,15,'\0',4),(226,15,'\0',5),(265,15,'\0',6),(307,15,'\0',7),(334,15,'\0',8),(375,15,'\0',9),(415,15,'\0',10),(31,16,'\0',NULL),(32,16,'\0',1),(82,16,'\0',2),(126,16,'\0',3),(169,16,'\0',4),(208,16,'\0',5),(250,16,'\0',6),(288,16,'\0',7),(328,16,'\0',8),(367,16,'\0',9),(409,16,'\0',10),(33,17,'\0',NULL),(34,17,'\0',1),(104,17,'\0',2),(143,17,'\0',3),(183,17,'\0',4),(223,17,'\0',5),(267,17,'\0',6),(309,17,'\0',7),(349,17,'\0',8),(389,17,'\0',9),(426,17,'\0',10),(35,18,'\0',NULL),(36,18,'\0',1),(84,18,'\0',2),(122,18,'\0',3),(164,18,'\0',4),(201,18,'\0',5),(241,18,'\0',6),(281,18,'\0',7),(323,18,'\0',8),(369,18,'\0',9),(411,18,'\0',10),(37,19,'\0',NULL),(38,19,'\0',1),(118,19,'\0',2),(159,19,'\0',3),(185,19,'\0',4),(225,19,'\0',5),(264,19,'\0',6),(305,19,'\0',7),(344,19,'\0',8),(383,19,'\0',9),(423,19,'\0',10),(39,20,'\0',NULL),(40,20,'\0',1),(103,20,'\0',2),(136,20,'\0',3),(177,20,'\0',4),(217,20,'\0',5),(260,20,'\0',6),(283,20,'\0',7),(326,20,'\0',8),(365,20,'\0',9),(407,20,'\0',10),(41,21,'\0',NULL),(42,21,'\0',1),(102,21,'\0',2),(142,21,'\0',3),(182,21,'\0',4),(216,21,'\0',5),(259,21,'\0',6),(299,21,'\0',7),(341,21,'\0',8),(364,21,'\0',9),(406,21,'\0',10),(43,22,'\0',NULL),(44,22,'\0',1),(114,22,'\0',2),(155,22,'\0',3),(199,22,'\0',4),(240,22,'\0',5),(280,22,'\0',6),(320,22,'\0',7),(356,22,'\0',8),(398,22,'\0',9),(437,22,'\0',10),(45,23,'\0',NULL),(46,23,'\0',1),(96,23,'\0',2),(130,23,'\0',3),(173,23,'\0',4),(211,23,'\0',5),(255,23,'\0',6),(300,23,'\0',7),(343,23,'\0',8),(382,23,'\0',9),(422,23,'\0',10),(47,24,'\0',NULL),(48,24,'\0',1),(115,24,'\0',2),(157,24,'\0',3),(197,24,'\0',4),(236,24,'\0',5),(271,24,'\0',6),(313,24,'\0',7),(352,24,'\0',8),(394,24,'\0',9),(438,24,'\0',10),(49,25,'\0',NULL),(50,25,'\0',1),(110,25,'\0',2),(148,25,'\0',3),(190,25,'\0',4),(212,25,'\0',5),(257,25,'\0',6),(297,25,'\0',7),(337,25,'\0',8),(372,25,'\0',9),(414,25,'\0',10),(51,26,'\0',NULL),(52,26,'\0',1),(90,26,'\0',2),(129,26,'\0',3),(166,26,'\0',4),(207,26,'\0',5),(248,26,'\0',6),(291,26,'\0',7),(353,26,'\0',8),(396,26,'\0',9),(435,26,'\0',10),(53,27,'\0',NULL),(54,27,'\0',1),(107,27,'\0',2),(149,27,'\0',3),(192,27,'\0',4),(230,27,'\0',5),(270,27,'\0',6),(306,27,'\0',7),(348,27,'\0',8),(387,27,'\0',9),(429,27,'\0',10),(55,28,'\0',NULL),(56,28,'\0',1),(81,28,'\0',2),(121,28,'\0',3),(161,28,'\0',4),(203,28,'\0',5),(249,28,'\0',6),(292,28,'\0',7),(331,28,'\0',8),(371,28,'\0',9),(408,28,'\0',10),(57,29,'\0',NULL),(58,29,'\0',1),(108,29,'\0',2),(146,29,'\0',3),(186,29,'\0',4),(222,29,'\0',5),(263,29,'\0',6),(303,29,'\0',7),(345,29,'\0',8),(388,29,'\0',9),(430,29,'\0',10),(59,30,'\0',NULL),(60,30,'\0',1),(99,30,'\0',2),(140,30,'\0',3),(163,30,'\0',4),(205,30,'\0',5),(245,30,'\0',6),(287,30,'\0',7),(322,30,'\0',8),(362,30,'\0',9),(403,30,'\0',10),(61,31,'\0',NULL),(62,31,'\0',1),(97,31,'\0',2),(137,31,'\0',3),(178,31,'\0',4),(218,31,'\0',5),(243,31,'\0',6),(284,31,'\0',7),(327,31,'\0',8),(366,31,'\0',9),(401,31,'\0',10),(63,32,'\0',NULL),(64,32,'\0',1),(119,32,'\0',2),(160,32,'\0',3),(200,32,'\0',4),(237,32,'\0',5),(277,32,'\0',6),(316,32,'\0',7),(357,32,'\0',8),(384,32,'\0',9),(424,32,'\0',10),(65,33,'\0',NULL),(66,33,'\0',1),(92,33,'\0',2),(132,33,'\0',3),(180,33,'\0',4),(220,33,'\0',5),(262,33,'\0',6),(302,33,'\0',7),(339,33,'\0',8),(379,33,'\0',9),(418,33,'\0',10),(67,34,'\0',NULL),(68,34,'\0',1),(117,34,'\0',2),(153,34,'\0',3),(194,34,'\0',4),(232,34,'\0',5),(273,34,'\0',6),(318,34,'\0',7),(359,34,'\0',8),(400,34,'\0',9),(440,34,'\0',10),(69,35,'\0',NULL),(70,35,'\0',1),(94,35,'\0',2),(134,35,'\0',3),(175,35,'\0',4),(214,35,'\0',5),(253,35,'\0',6),(294,35,'\0',7),(333,35,'\0',8),(374,35,'\0',9),(420,35,'\0',10),(71,36,'\0',NULL),(72,36,'\0',1),(87,36,'\0',2),(125,36,'\0',3),(168,36,'\0',4),(234,36,'\0',5),(275,36,'\0',6),(315,36,'\0',7),(355,36,'\0',8),(392,36,'\0',9),(432,36,'\0',10),(73,37,'\0',NULL),(74,37,'\0',1),(112,37,'\0',2),(151,37,'\0',3),(188,37,'\0',4),(227,37,'\0',5),(266,37,'\0',6),(308,37,'\0',7),(335,37,'\0',8),(376,37,'\0',9),(416,37,'\0',10),(75,38,'\0',NULL),(76,38,'\0',1),(83,38,'\0',2),(127,38,'\0',3),(170,38,'\0',4),(209,38,'\0',5),(251,38,'\0',6),(289,38,'\0',7),(329,38,'\0',8),(368,38,'\0',9),(410,38,'\0',10),(77,39,'\0',NULL),(78,39,'\0',1),(105,39,'\0',2),(144,39,'\0',3),(184,39,'\0',4),(224,39,'\0',5),(268,39,'\0',6),(310,39,'\0',7),(350,39,'\0',8),(390,39,'\0',9),(427,39,'\0',10),(79,40,'\0',NULL),(80,40,'\0',1),(85,40,'\0',2),(123,40,'\0',3),(165,40,'\0',4),(202,40,'\0',5),(242,40,'\0',6),(282,40,'\0',7),(324,40,'\0',8),(370,40,'\0',9),(412,40,'\0',10); +/*!40000 ALTER TABLE `acl2` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `acl2_permissions` +-- + +DROP TABLE IF EXISTS `acl2_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `acl2_permissions` ( + `acl_id` bigint(20) NOT NULL, + `permissions` int(11) DEFAULT NULL, + `admin_id` bigint(20) NOT NULL, + PRIMARY KEY (`acl_id`,`admin_id`), + KEY `FK35C6CFADA4AD9904` (`admin_id`), + KEY `FK35C6CFADD91CE8A3` (`acl_id`), + CONSTRAINT `FK35C6CFADA4AD9904` FOREIGN KEY (`admin_id`) REFERENCES `admins` (`adminid`), + CONSTRAINT `FK35C6CFADD91CE8A3` FOREIGN KEY (`acl_id`) REFERENCES `acl2` (`acl_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `acl2_permissions` +-- + +LOCK TABLES `acl2_permissions` WRITE; +/*!40000 ALTER TABLE `acl2_permissions` DISABLE KEYS */; +INSERT INTO `acl2_permissions` VALUES (1,16383,1),(1,16383,2),(1,16383,6),(1,16383,7),(1,16383,8),(2,16383,1),(2,16383,2),(2,16383,6),(2,16383,7),(2,16383,8),(3,16383,1),(3,16383,2),(3,16383,6),(3,16383,7),(3,16383,8),(4,16383,1),(4,16383,2),(4,16383,6),(4,16383,7),(4,16383,8),(5,16383,1),(5,16383,2),(5,16383,6),(5,16383,7),(5,16383,8),(6,16383,1),(6,16383,2),(6,16383,6),(6,16383,7),(6,16383,8),(7,16383,1),(7,16383,2),(7,16383,6),(7,16383,7),(7,16383,8),(8,16383,1),(8,16383,2),(8,16383,6),(8,16383,7),(8,16383,8),(9,16383,1),(9,16383,2),(9,16383,6),(9,16383,7),(9,16383,8),(10,16383,1),(10,16383,2),(10,16383,6),(10,16383,7),(10,16383,8),(11,16383,1),(11,16383,2),(11,16383,6),(11,16383,7),(11,16383,8),(12,16383,1),(12,16383,2),(12,16383,6),(12,16383,7),(12,16383,8),(13,16383,1),(13,16383,2),(13,16383,6),(13,16383,7),(13,16383,8),(14,16383,1),(14,16383,2),(14,16383,6),(14,16383,7),(14,16383,8),(15,16383,1),(15,16383,2),(15,16383,6),(15,16383,7),(15,16383,8),(16,16383,1),(16,16383,2),(16,16383,6),(16,16383,7),(16,16383,8),(17,16383,1),(17,16383,2),(17,16383,6),(17,16383,7),(17,16383,8),(18,16383,1),(18,16383,2),(18,16383,6),(18,16383,7),(18,16383,8),(19,16383,1),(19,16383,2),(19,16383,6),(19,16383,7),(19,16383,8),(20,16383,1),(20,16383,2),(20,16383,6),(20,16383,7),(20,16383,8),(21,16383,1),(21,16383,2),(21,16383,6),(21,16383,7),(21,16383,8),(22,16383,1),(22,16383,2),(22,16383,6),(22,16383,7),(22,16383,8),(23,16383,1),(23,16383,2),(23,16383,6),(23,16383,7),(23,16383,8),(24,16383,1),(24,16383,2),(24,16383,6),(24,16383,7),(24,16383,8),(25,16383,1),(25,16383,2),(25,16383,6),(25,16383,7),(25,16383,8),(26,16383,1),(26,16383,2),(26,16383,6),(26,16383,7),(26,16383,8),(27,16383,1),(27,16383,2),(27,16383,6),(27,16383,7),(27,16383,8),(28,16383,1),(28,16383,2),(28,16383,6),(28,16383,7),(28,16383,8),(29,16383,1),(29,16383,2),(29,16383,6),(29,16383,7),(29,16383,8),(30,16383,1),(30,16383,2),(30,16383,6),(30,16383,7),(30,16383,8),(31,16383,1),(31,16383,2),(31,16383,6),(31,16383,7),(31,16383,8),(32,16383,1),(32,16383,2),(32,16383,6),(32,16383,7),(32,16383,8),(33,16383,1),(33,16383,2),(33,16383,6),(33,16383,7),(33,16383,8),(34,16383,1),(34,16383,2),(34,16383,6),(34,16383,7),(34,16383,8),(35,16383,1),(35,16383,2),(35,16383,6),(35,16383,7),(35,16383,8),(36,16383,1),(36,16383,2),(36,16383,6),(36,16383,7),(36,16383,8),(37,16383,1),(37,16383,2),(37,16383,6),(37,16383,7),(37,16383,8),(38,16383,1),(38,16383,2),(38,16383,6),(38,16383,7),(38,16383,8),(39,16383,1),(39,16383,2),(39,16383,6),(39,16383,7),(39,16383,8),(40,16383,1),(40,16383,2),(40,16383,6),(40,16383,7),(40,16383,8),(41,16383,1),(41,16383,2),(41,16383,6),(41,16383,7),(41,16383,8),(42,16383,1),(42,16383,2),(42,16383,6),(42,16383,7),(42,16383,8),(43,16383,1),(43,16383,2),(43,16383,6),(43,16383,7),(43,16383,8),(44,16383,1),(44,16383,2),(44,16383,6),(44,16383,7),(44,16383,8),(45,16383,1),(45,16383,2),(45,16383,6),(45,16383,7),(45,16383,8),(46,16383,1),(46,16383,2),(46,16383,6),(46,16383,7),(46,16383,8),(47,16383,1),(47,16383,2),(47,16383,6),(47,16383,7),(47,16383,8),(48,16383,1),(48,16383,2),(48,16383,6),(48,16383,7),(48,16383,8),(49,16383,1),(49,16383,2),(49,16383,6),(49,16383,7),(49,16383,8),(50,16383,1),(50,16383,2),(50,16383,6),(50,16383,7),(50,16383,8),(51,16383,1),(51,16383,2),(51,16383,6),(51,16383,7),(51,16383,8),(52,16383,1),(52,16383,2),(52,16383,6),(52,16383,7),(52,16383,8),(53,16383,1),(53,16383,2),(53,16383,6),(53,16383,7),(53,16383,8),(54,16383,1),(54,16383,2),(54,16383,6),(54,16383,7),(54,16383,8),(55,16383,1),(55,16383,2),(55,16383,6),(55,16383,7),(55,16383,8),(56,16383,1),(56,16383,2),(56,16383,6),(56,16383,7),(56,16383,8),(57,16383,1),(57,16383,2),(57,16383,6),(57,16383,7),(57,16383,8),(58,16383,1),(58,16383,2),(58,16383,6),(58,16383,7),(58,16383,8),(59,16383,1),(59,16383,2),(59,16383,6),(59,16383,7),(59,16383,8),(60,16383,1),(60,16383,2),(60,16383,6),(60,16383,7),(60,16383,8),(61,16383,1),(61,16383,2),(61,16383,6),(61,16383,7),(61,16383,8),(62,16383,1),(62,16383,2),(62,16383,6),(62,16383,7),(62,16383,8),(63,16383,1),(63,16383,2),(63,16383,6),(63,16383,7),(63,16383,8),(64,16383,1),(64,16383,2),(64,16383,6),(64,16383,7),(64,16383,8),(65,16383,1),(65,16383,2),(65,16383,6),(65,16383,7),(65,16383,8),(66,16383,1),(66,16383,2),(66,16383,6),(66,16383,7),(66,16383,8),(67,16383,1),(67,16383,2),(67,16383,6),(67,16383,7),(67,16383,8),(68,16383,1),(68,16383,2),(68,16383,6),(68,16383,7),(68,16383,8),(69,16383,1),(69,16383,2),(69,16383,6),(69,16383,7),(69,16383,8),(70,16383,1),(70,16383,2),(70,16383,6),(70,16383,7),(70,16383,8),(71,16383,1),(71,16383,2),(71,16383,6),(71,16383,7),(71,16383,8),(72,16383,1),(72,16383,2),(72,16383,6),(72,16383,7),(72,16383,8),(73,16383,1),(73,16383,2),(73,16383,6),(73,16383,7),(73,16383,8),(74,16383,1),(74,16383,2),(74,16383,6),(74,16383,7),(74,16383,8),(75,16383,1),(75,16383,2),(75,16383,6),(75,16383,7),(75,16383,8),(76,16383,1),(76,16383,2),(76,16383,6),(76,16383,7),(76,16383,8),(77,16383,1),(77,16383,2),(77,16383,6),(77,16383,7),(77,16383,8),(78,16383,1),(78,16383,2),(78,16383,6),(78,16383,7),(78,16383,8),(79,16383,1),(79,16383,2),(79,16383,6),(79,16383,7),(79,16383,8),(80,16383,1),(80,16383,2),(80,16383,6),(80,16383,7),(80,16383,8),(81,16383,1),(81,16383,2),(81,16383,6),(81,16383,7),(81,16383,8),(82,16383,1),(82,16383,2),(82,16383,6),(82,16383,7),(82,16383,8),(83,16383,1),(83,16383,2),(83,16383,6),(83,16383,7),(83,16383,8),(84,16383,1),(84,16383,2),(84,16383,6),(84,16383,7),(84,16383,8),(85,16383,1),(85,16383,2),(85,16383,6),(85,16383,7),(85,16383,8),(86,16383,1),(86,16383,2),(86,16383,6),(86,16383,7),(86,16383,8),(87,16383,1),(87,16383,2),(87,16383,6),(87,16383,7),(87,16383,8),(88,16383,1),(88,16383,2),(88,16383,6),(88,16383,7),(88,16383,8),(89,16383,1),(89,16383,2),(89,16383,6),(89,16383,7),(89,16383,8),(90,16383,1),(90,16383,2),(90,16383,6),(90,16383,7),(90,16383,8),(91,16383,1),(91,16383,2),(91,16383,6),(91,16383,7),(91,16383,8),(92,16383,1),(92,16383,2),(92,16383,6),(92,16383,7),(92,16383,8),(93,16383,1),(93,16383,2),(93,16383,6),(93,16383,7),(93,16383,8),(94,16383,1),(94,16383,2),(94,16383,6),(94,16383,7),(94,16383,8),(95,16383,1),(95,16383,2),(95,16383,6),(95,16383,7),(95,16383,8),(96,16383,1),(96,16383,2),(96,16383,6),(96,16383,7),(96,16383,8),(97,16383,1),(97,16383,2),(97,16383,6),(97,16383,7),(97,16383,8),(98,16383,1),(98,16383,2),(98,16383,6),(98,16383,7),(98,16383,8),(99,16383,1),(99,16383,2),(99,16383,6),(99,16383,7),(99,16383,8),(100,16383,1),(100,16383,2),(100,16383,6),(100,16383,7),(100,16383,8),(101,16383,1),(101,16383,2),(101,16383,6),(101,16383,7),(101,16383,8),(102,16383,1),(102,16383,2),(102,16383,6),(102,16383,7),(102,16383,8),(103,16383,1),(103,16383,2),(103,16383,6),(103,16383,7),(103,16383,8),(104,16383,1),(104,16383,2),(104,16383,6),(104,16383,7),(104,16383,8),(105,16383,1),(105,16383,2),(105,16383,6),(105,16383,7),(105,16383,8),(106,16383,1),(106,16383,2),(106,16383,6),(106,16383,7),(106,16383,8),(107,16383,1),(107,16383,2),(107,16383,6),(107,16383,7),(107,16383,8),(108,16383,1),(108,16383,2),(108,16383,6),(108,16383,7),(108,16383,8),(109,16383,1),(109,16383,2),(109,16383,6),(109,16383,7),(109,16383,8),(110,16383,1),(110,16383,2),(110,16383,6),(110,16383,7),(110,16383,8),(111,16383,1),(111,16383,2),(111,16383,6),(111,16383,7),(111,16383,8),(112,16383,1),(112,16383,2),(112,16383,6),(112,16383,7),(112,16383,8),(113,16383,1),(113,16383,2),(113,16383,6),(113,16383,7),(113,16383,8),(114,16383,1),(114,16383,2),(114,16383,6),(114,16383,7),(114,16383,8),(115,16383,1),(115,16383,2),(115,16383,6),(115,16383,7),(115,16383,8),(116,16383,1),(116,16383,2),(116,16383,6),(116,16383,7),(116,16383,8),(117,16383,1),(117,16383,2),(117,16383,6),(117,16383,7),(117,16383,8),(118,16383,1),(118,16383,2),(118,16383,6),(118,16383,7),(118,16383,8),(119,16383,1),(119,16383,2),(119,16383,6),(119,16383,7),(119,16383,8),(120,16383,1),(120,16383,2),(120,16383,6),(120,16383,7),(120,16383,8),(121,16383,1),(121,16383,2),(121,16383,6),(121,16383,7),(121,16383,8),(122,16383,1),(122,16383,2),(122,16383,6),(122,16383,7),(122,16383,8),(123,16383,1),(123,16383,2),(123,16383,6),(123,16383,7),(123,16383,8),(124,16383,1),(124,16383,2),(124,16383,6),(124,16383,7),(124,16383,8),(125,16383,1),(125,16383,2),(125,16383,6),(125,16383,7),(125,16383,8),(126,16383,1),(126,16383,2),(126,16383,6),(126,16383,7),(126,16383,8),(127,16383,1),(127,16383,2),(127,16383,6),(127,16383,7),(127,16383,8),(128,16383,1),(128,16383,2),(128,16383,6),(128,16383,7),(128,16383,8),(129,16383,1),(129,16383,2),(129,16383,6),(129,16383,7),(129,16383,8),(130,16383,1),(130,16383,2),(130,16383,6),(130,16383,7),(130,16383,8),(131,16383,1),(131,16383,2),(131,16383,6),(131,16383,7),(131,16383,8),(132,16383,1),(132,16383,2),(132,16383,6),(132,16383,7),(132,16383,8),(133,16383,1),(133,16383,2),(133,16383,6),(133,16383,7),(133,16383,8),(134,16383,1),(134,16383,2),(134,16383,6),(134,16383,7),(134,16383,8),(135,16383,1),(135,16383,2),(135,16383,6),(135,16383,7),(135,16383,8),(136,16383,1),(136,16383,2),(136,16383,6),(136,16383,7),(136,16383,8),(137,16383,1),(137,16383,2),(137,16383,6),(137,16383,7),(137,16383,8),(138,16383,1),(138,16383,2),(138,16383,6),(138,16383,7),(138,16383,8),(139,16383,1),(139,16383,2),(139,16383,6),(139,16383,7),(139,16383,8),(140,16383,1),(140,16383,2),(140,16383,6),(140,16383,7),(140,16383,8),(141,16383,1),(141,16383,2),(141,16383,6),(141,16383,7),(141,16383,8),(142,16383,1),(142,16383,2),(142,16383,6),(142,16383,7),(142,16383,8),(143,16383,1),(143,16383,2),(143,16383,6),(143,16383,7),(143,16383,8),(144,16383,1),(144,16383,2),(144,16383,6),(144,16383,7),(144,16383,8),(145,16383,1),(145,16383,2),(145,16383,6),(145,16383,7),(145,16383,8),(146,16383,1),(146,16383,2),(146,16383,6),(146,16383,7),(146,16383,8),(147,16383,1),(147,16383,2),(147,16383,6),(147,16383,7),(147,16383,8),(148,16383,1),(148,16383,2),(148,16383,6),(148,16383,7),(148,16383,8),(149,16383,1),(149,16383,2),(149,16383,6),(149,16383,7),(149,16383,8),(150,16383,1),(150,16383,2),(150,16383,6),(150,16383,7),(150,16383,8),(151,16383,1),(151,16383,2),(151,16383,6),(151,16383,7),(151,16383,8),(152,16383,1),(152,16383,2),(152,16383,6),(152,16383,7),(152,16383,8),(153,16383,1),(153,16383,2),(153,16383,6),(153,16383,7),(153,16383,8),(154,16383,1),(154,16383,2),(154,16383,6),(154,16383,7),(154,16383,8),(155,16383,1),(155,16383,2),(155,16383,6),(155,16383,7),(155,16383,8),(156,16383,1),(156,16383,2),(156,16383,6),(156,16383,7),(156,16383,8),(157,16383,1),(157,16383,2),(157,16383,6),(157,16383,7),(157,16383,8),(158,16383,1),(158,16383,2),(158,16383,6),(158,16383,7),(158,16383,8),(159,16383,1),(159,16383,2),(159,16383,6),(159,16383,7),(159,16383,8),(160,16383,1),(160,16383,2),(160,16383,6),(160,16383,7),(160,16383,8),(161,16383,1),(161,16383,2),(161,16383,6),(161,16383,7),(161,16383,8),(162,16383,1),(162,16383,2),(162,16383,6),(162,16383,7),(162,16383,8),(163,16383,1),(163,16383,2),(163,16383,6),(163,16383,7),(163,16383,8),(164,16383,1),(164,16383,2),(164,16383,6),(164,16383,7),(164,16383,8),(165,16383,1),(165,16383,2),(165,16383,6),(165,16383,7),(165,16383,8),(166,16383,1),(166,16383,2),(166,16383,6),(166,16383,7),(166,16383,8),(167,16383,1),(167,16383,2),(167,16383,6),(167,16383,7),(167,16383,8),(168,16383,1),(168,16383,2),(168,16383,6),(168,16383,7),(168,16383,8),(169,16383,1),(169,16383,2),(169,16383,6),(169,16383,7),(169,16383,8),(170,16383,1),(170,16383,2),(170,16383,6),(170,16383,7),(170,16383,8),(171,16383,1),(171,16383,2),(171,16383,6),(171,16383,7),(171,16383,8),(172,16383,1),(172,16383,2),(172,16383,6),(172,16383,7),(172,16383,8),(173,16383,1),(173,16383,2),(173,16383,6),(173,16383,7),(173,16383,8),(174,16383,1),(174,16383,2),(174,16383,6),(174,16383,7),(174,16383,8),(175,16383,1),(175,16383,2),(175,16383,6),(175,16383,7),(175,16383,8),(176,16383,1),(176,16383,2),(176,16383,6),(176,16383,7),(176,16383,8),(177,16383,1),(177,16383,2),(177,16383,6),(177,16383,7),(177,16383,8),(178,16383,1),(178,16383,2),(178,16383,6),(178,16383,7),(178,16383,8),(179,16383,1),(179,16383,2),(179,16383,6),(179,16383,7),(179,16383,8),(180,16383,1),(180,16383,2),(180,16383,6),(180,16383,7),(180,16383,8),(181,16383,1),(181,16383,2),(181,16383,6),(181,16383,7),(181,16383,8),(182,16383,1),(182,16383,2),(182,16383,6),(182,16383,7),(182,16383,8),(183,16383,1),(183,16383,2),(183,16383,6),(183,16383,7),(183,16383,8),(184,16383,1),(184,16383,2),(184,16383,6),(184,16383,7),(184,16383,8),(185,16383,1),(185,16383,2),(185,16383,6),(185,16383,7),(185,16383,8),(186,16383,1),(186,16383,2),(186,16383,6),(186,16383,7),(186,16383,8),(187,16383,1),(187,16383,2),(187,16383,6),(187,16383,7),(187,16383,8),(188,16383,1),(188,16383,2),(188,16383,6),(188,16383,7),(188,16383,8),(189,16383,1),(189,16383,2),(189,16383,6),(189,16383,7),(189,16383,8),(190,16383,1),(190,16383,2),(190,16383,6),(190,16383,7),(190,16383,8),(191,16383,1),(191,16383,2),(191,16383,6),(191,16383,7),(191,16383,8),(192,16383,1),(192,16383,2),(192,16383,6),(192,16383,7),(192,16383,8),(193,16383,1),(193,16383,2),(193,16383,6),(193,16383,7),(193,16383,8),(194,16383,1),(194,16383,2),(194,16383,6),(194,16383,7),(194,16383,8),(195,16383,1),(195,16383,2),(195,16383,6),(195,16383,7),(195,16383,8),(196,16383,1),(196,16383,2),(196,16383,6),(196,16383,7),(196,16383,8),(197,16383,1),(197,16383,2),(197,16383,6),(197,16383,7),(197,16383,8),(198,16383,1),(198,16383,2),(198,16383,6),(198,16383,7),(198,16383,8),(199,16383,1),(199,16383,2),(199,16383,6),(199,16383,7),(199,16383,8),(200,16383,1),(200,16383,2),(200,16383,6),(200,16383,7),(200,16383,8),(201,16383,1),(201,16383,2),(201,16383,6),(201,16383,7),(201,16383,8),(202,16383,1),(202,16383,2),(202,16383,6),(202,16383,7),(202,16383,8),(203,16383,1),(203,16383,2),(203,16383,6),(203,16383,7),(203,16383,8),(204,16383,1),(204,16383,2),(204,16383,6),(204,16383,7),(204,16383,8),(205,16383,1),(205,16383,2),(205,16383,6),(205,16383,7),(205,16383,8),(206,16383,1),(206,16383,2),(206,16383,6),(206,16383,7),(206,16383,8),(207,16383,1),(207,16383,2),(207,16383,6),(207,16383,7),(207,16383,8),(208,16383,1),(208,16383,2),(208,16383,6),(208,16383,7),(208,16383,8),(209,16383,1),(209,16383,2),(209,16383,6),(209,16383,7),(209,16383,8),(210,16383,1),(210,16383,2),(210,16383,6),(210,16383,7),(210,16383,8),(211,16383,1),(211,16383,2),(211,16383,6),(211,16383,7),(211,16383,8),(212,16383,1),(212,16383,2),(212,16383,6),(212,16383,7),(212,16383,8),(213,16383,1),(213,16383,2),(213,16383,6),(213,16383,7),(213,16383,8),(214,16383,1),(214,16383,2),(214,16383,6),(214,16383,7),(214,16383,8),(215,16383,1),(215,16383,2),(215,16383,6),(215,16383,7),(215,16383,8),(216,16383,1),(216,16383,2),(216,16383,6),(216,16383,7),(216,16383,8),(217,16383,1),(217,16383,2),(217,16383,6),(217,16383,7),(217,16383,8),(218,16383,1),(218,16383,2),(218,16383,6),(218,16383,7),(218,16383,8),(219,16383,1),(219,16383,2),(219,16383,6),(219,16383,7),(219,16383,8),(220,16383,1),(220,16383,2),(220,16383,6),(220,16383,7),(220,16383,8),(221,16383,1),(221,16383,2),(221,16383,6),(221,16383,7),(221,16383,8),(222,16383,1),(222,16383,2),(222,16383,6),(222,16383,7),(222,16383,8),(223,16383,1),(223,16383,2),(223,16383,6),(223,16383,7),(223,16383,8),(224,16383,1),(224,16383,2),(224,16383,6),(224,16383,7),(224,16383,8),(225,16383,1),(225,16383,2),(225,16383,6),(225,16383,7),(225,16383,8),(226,16383,1),(226,16383,2),(226,16383,6),(226,16383,7),(226,16383,8),(227,16383,1),(227,16383,2),(227,16383,6),(227,16383,7),(227,16383,8),(228,16383,1),(228,16383,2),(228,16383,6),(228,16383,7),(228,16383,8),(229,16383,1),(229,16383,2),(229,16383,6),(229,16383,7),(229,16383,8),(230,16383,1),(230,16383,2),(230,16383,6),(230,16383,7),(230,16383,8),(231,16383,1),(231,16383,2),(231,16383,6),(231,16383,7),(231,16383,8),(232,16383,1),(232,16383,2),(232,16383,6),(232,16383,7),(232,16383,8),(233,16383,1),(233,16383,2),(233,16383,6),(233,16383,7),(233,16383,8),(234,16383,1),(234,16383,2),(234,16383,6),(234,16383,7),(234,16383,8),(235,16383,1),(235,16383,2),(235,16383,6),(235,16383,7),(235,16383,8),(236,16383,1),(236,16383,2),(236,16383,6),(236,16383,7),(236,16383,8),(237,16383,1),(237,16383,2),(237,16383,6),(237,16383,7),(237,16383,8),(238,16383,1),(238,16383,2),(238,16383,6),(238,16383,7),(238,16383,8),(239,16383,1),(239,16383,2),(239,16383,6),(239,16383,7),(239,16383,8),(240,16383,1),(240,16383,2),(240,16383,6),(240,16383,7),(240,16383,8),(241,16383,1),(241,16383,2),(241,16383,6),(241,16383,7),(241,16383,8),(242,16383,1),(242,16383,2),(242,16383,6),(242,16383,7),(242,16383,8),(243,16383,1),(243,16383,2),(243,16383,6),(243,16383,7),(243,16383,8),(244,16383,1),(244,16383,2),(244,16383,6),(244,16383,7),(244,16383,8),(245,16383,1),(245,16383,2),(245,16383,6),(245,16383,7),(245,16383,8),(246,16383,1),(246,16383,2),(246,16383,6),(246,16383,7),(246,16383,8),(247,16383,1),(247,16383,2),(247,16383,6),(247,16383,7),(247,16383,8),(248,16383,1),(248,16383,2),(248,16383,6),(248,16383,7),(248,16383,8),(249,16383,1),(249,16383,2),(249,16383,6),(249,16383,7),(249,16383,8),(250,16383,1),(250,16383,2),(250,16383,6),(250,16383,7),(250,16383,8),(251,16383,1),(251,16383,2),(251,16383,6),(251,16383,7),(251,16383,8),(252,16383,1),(252,16383,2),(252,16383,6),(252,16383,7),(252,16383,8),(253,16383,1),(253,16383,2),(253,16383,6),(253,16383,7),(253,16383,8),(254,16383,1),(254,16383,2),(254,16383,6),(254,16383,7),(254,16383,8),(255,16383,1),(255,16383,2),(255,16383,6),(255,16383,7),(255,16383,8),(256,16383,1),(256,16383,2),(256,16383,6),(256,16383,7),(256,16383,8),(257,16383,1),(257,16383,2),(257,16383,6),(257,16383,7),(257,16383,8),(258,16383,1),(258,16383,2),(258,16383,6),(258,16383,7),(258,16383,8),(259,16383,1),(259,16383,2),(259,16383,6),(259,16383,7),(259,16383,8),(260,16383,1),(260,16383,2),(260,16383,6),(260,16383,7),(260,16383,8),(261,16383,1),(261,16383,2),(261,16383,6),(261,16383,7),(261,16383,8),(262,16383,1),(262,16383,2),(262,16383,6),(262,16383,7),(262,16383,8),(263,16383,1),(263,16383,2),(263,16383,6),(263,16383,7),(263,16383,8),(264,16383,1),(264,16383,2),(264,16383,6),(264,16383,7),(264,16383,8),(265,16383,1),(265,16383,2),(265,16383,6),(265,16383,7),(265,16383,8),(266,16383,1),(266,16383,2),(266,16383,6),(266,16383,7),(266,16383,8),(267,16383,1),(267,16383,2),(267,16383,6),(267,16383,7),(267,16383,8),(268,16383,1),(268,16383,2),(268,16383,6),(268,16383,7),(268,16383,8),(269,16383,1),(269,16383,2),(269,16383,6),(269,16383,7),(269,16383,8),(270,16383,1),(270,16383,2),(270,16383,6),(270,16383,7),(270,16383,8),(271,16383,1),(271,16383,2),(271,16383,6),(271,16383,7),(271,16383,8),(272,16383,1),(272,16383,2),(272,16383,6),(272,16383,7),(272,16383,8),(273,16383,1),(273,16383,2),(273,16383,6),(273,16383,7),(273,16383,8),(274,16383,1),(274,16383,2),(274,16383,6),(274,16383,7),(274,16383,8),(275,16383,1),(275,16383,2),(275,16383,6),(275,16383,7),(275,16383,8),(276,16383,1),(276,16383,2),(276,16383,6),(276,16383,7),(276,16383,8),(277,16383,1),(277,16383,2),(277,16383,6),(277,16383,7),(277,16383,8),(278,16383,1),(278,16383,2),(278,16383,6),(278,16383,7),(278,16383,8),(279,16383,1),(279,16383,2),(279,16383,6),(279,16383,7),(279,16383,8),(280,16383,1),(280,16383,2),(280,16383,6),(280,16383,7),(280,16383,8),(281,16383,1),(281,16383,2),(281,16383,6),(281,16383,7),(281,16383,8),(282,16383,1),(282,16383,2),(282,16383,6),(282,16383,7),(282,16383,8),(283,16383,1),(283,16383,2),(283,16383,6),(283,16383,7),(283,16383,8),(284,16383,1),(284,16383,2),(284,16383,6),(284,16383,7),(284,16383,8),(285,16383,1),(285,16383,2),(285,16383,6),(285,16383,7),(285,16383,8),(286,16383,1),(286,16383,2),(286,16383,6),(286,16383,7),(286,16383,8),(287,16383,1),(287,16383,2),(287,16383,6),(287,16383,7),(287,16383,8),(288,16383,1),(288,16383,2),(288,16383,6),(288,16383,7),(288,16383,8),(289,16383,1),(289,16383,2),(289,16383,6),(289,16383,7),(289,16383,8),(290,16383,1),(290,16383,2),(290,16383,6),(290,16383,7),(290,16383,8),(291,16383,1),(291,16383,2),(291,16383,6),(291,16383,7),(291,16383,8),(292,16383,1),(292,16383,2),(292,16383,6),(292,16383,7),(292,16383,8),(293,16383,1),(293,16383,2),(293,16383,6),(293,16383,7),(293,16383,8),(294,16383,1),(294,16383,2),(294,16383,6),(294,16383,7),(294,16383,8),(295,16383,1),(295,16383,2),(295,16383,6),(295,16383,7),(295,16383,8),(296,16383,1),(296,16383,2),(296,16383,6),(296,16383,7),(296,16383,8),(297,16383,1),(297,16383,2),(297,16383,6),(297,16383,7),(297,16383,8),(298,16383,1),(298,16383,2),(298,16383,6),(298,16383,7),(298,16383,8),(299,16383,1),(299,16383,2),(299,16383,6),(299,16383,7),(299,16383,8),(300,16383,1),(300,16383,2),(300,16383,6),(300,16383,7),(300,16383,8),(301,16383,1),(301,16383,2),(301,16383,6),(301,16383,7),(301,16383,8),(302,16383,1),(302,16383,2),(302,16383,6),(302,16383,7),(302,16383,8),(303,16383,1),(303,16383,2),(303,16383,6),(303,16383,7),(303,16383,8),(304,16383,1),(304,16383,2),(304,16383,6),(304,16383,7),(304,16383,8),(305,16383,1),(305,16383,2),(305,16383,6),(305,16383,7),(305,16383,8),(306,16383,1),(306,16383,2),(306,16383,6),(306,16383,7),(306,16383,8),(307,16383,1),(307,16383,2),(307,16383,6),(307,16383,7),(307,16383,8),(308,16383,1),(308,16383,2),(308,16383,6),(308,16383,7),(308,16383,8),(309,16383,1),(309,16383,2),(309,16383,6),(309,16383,7),(309,16383,8),(310,16383,1),(310,16383,2),(310,16383,6),(310,16383,7),(310,16383,8),(311,16383,1),(311,16383,2),(311,16383,6),(311,16383,7),(311,16383,8),(312,16383,1),(312,16383,2),(312,16383,6),(312,16383,7),(312,16383,8),(313,16383,1),(313,16383,2),(313,16383,6),(313,16383,7),(313,16383,8),(314,16383,1),(314,16383,2),(314,16383,6),(314,16383,7),(314,16383,8),(315,16383,1),(315,16383,2),(315,16383,6),(315,16383,7),(315,16383,8),(316,16383,1),(316,16383,2),(316,16383,6),(316,16383,7),(316,16383,8),(317,16383,1),(317,16383,2),(317,16383,6),(317,16383,7),(317,16383,8),(318,16383,1),(318,16383,2),(318,16383,6),(318,16383,7),(318,16383,8),(319,16383,1),(319,16383,2),(319,16383,6),(319,16383,7),(319,16383,8),(320,16383,1),(320,16383,2),(320,16383,6),(320,16383,7),(320,16383,8),(321,16383,1),(321,16383,2),(321,16383,6),(321,16383,7),(321,16383,8),(322,16383,1),(322,16383,2),(322,16383,6),(322,16383,7),(322,16383,8),(323,16383,1),(323,16383,2),(323,16383,6),(323,16383,7),(323,16383,8),(324,16383,1),(324,16383,2),(324,16383,6),(324,16383,7),(324,16383,8),(325,16383,1),(325,16383,2),(325,16383,6),(325,16383,7),(325,16383,8),(326,16383,1),(326,16383,2),(326,16383,6),(326,16383,7),(326,16383,8),(327,16383,1),(327,16383,2),(327,16383,6),(327,16383,7),(327,16383,8),(328,16383,1),(328,16383,2),(328,16383,6),(328,16383,7),(328,16383,8),(329,16383,1),(329,16383,2),(329,16383,6),(329,16383,7),(329,16383,8),(330,16383,1),(330,16383,2),(330,16383,6),(330,16383,7),(330,16383,8),(331,16383,1),(331,16383,2),(331,16383,6),(331,16383,7),(331,16383,8),(332,16383,1),(332,16383,2),(332,16383,6),(332,16383,7),(332,16383,8),(333,16383,1),(333,16383,2),(333,16383,6),(333,16383,7),(333,16383,8),(334,16383,1),(334,16383,2),(334,16383,6),(334,16383,7),(334,16383,8),(335,16383,1),(335,16383,2),(335,16383,6),(335,16383,7),(335,16383,8),(336,16383,1),(336,16383,2),(336,16383,6),(336,16383,7),(336,16383,8),(337,16383,1),(337,16383,2),(337,16383,6),(337,16383,7),(337,16383,8),(338,16383,1),(338,16383,2),(338,16383,6),(338,16383,7),(338,16383,8),(339,16383,1),(339,16383,2),(339,16383,6),(339,16383,7),(339,16383,8),(340,16383,1),(340,16383,2),(340,16383,6),(340,16383,7),(340,16383,8),(341,16383,1),(341,16383,2),(341,16383,6),(341,16383,7),(341,16383,8),(342,16383,1),(342,16383,2),(342,16383,6),(342,16383,7),(342,16383,8),(343,16383,1),(343,16383,2),(343,16383,6),(343,16383,7),(343,16383,8),(344,16383,1),(344,16383,2),(344,16383,6),(344,16383,7),(344,16383,8),(345,16383,1),(345,16383,2),(345,16383,6),(345,16383,7),(345,16383,8),(346,16383,1),(346,16383,2),(346,16383,6),(346,16383,7),(346,16383,8),(347,16383,1),(347,16383,2),(347,16383,6),(347,16383,7),(347,16383,8),(348,16383,1),(348,16383,2),(348,16383,6),(348,16383,7),(348,16383,8),(349,16383,1),(349,16383,2),(349,16383,6),(349,16383,7),(349,16383,8),(350,16383,1),(350,16383,2),(350,16383,6),(350,16383,7),(350,16383,8),(351,16383,1),(351,16383,2),(351,16383,6),(351,16383,7),(351,16383,8),(352,16383,1),(352,16383,2),(352,16383,6),(352,16383,7),(352,16383,8),(353,16383,1),(353,16383,2),(353,16383,6),(353,16383,7),(353,16383,8),(354,16383,1),(354,16383,2),(354,16383,6),(354,16383,7),(354,16383,8),(355,16383,1),(355,16383,2),(355,16383,6),(355,16383,7),(355,16383,8),(356,16383,1),(356,16383,2),(356,16383,6),(356,16383,7),(356,16383,8),(357,16383,1),(357,16383,2),(357,16383,6),(357,16383,7),(357,16383,8),(358,16383,1),(358,16383,2),(358,16383,6),(358,16383,7),(358,16383,8),(359,16383,1),(359,16383,2),(359,16383,6),(359,16383,7),(359,16383,8),(360,16383,1),(360,16383,2),(360,16383,6),(360,16383,7),(360,16383,8),(361,16383,1),(361,16383,2),(361,16383,6),(361,16383,7),(361,16383,8),(362,16383,1),(362,16383,2),(362,16383,6),(362,16383,7),(362,16383,8),(363,16383,1),(363,16383,2),(363,16383,6),(363,16383,7),(363,16383,8),(364,16383,1),(364,16383,2),(364,16383,6),(364,16383,7),(364,16383,8),(365,16383,1),(365,16383,2),(365,16383,6),(365,16383,7),(365,16383,8),(366,16383,1),(366,16383,2),(366,16383,6),(366,16383,7),(366,16383,8),(367,16383,1),(367,16383,2),(367,16383,6),(367,16383,7),(367,16383,8),(368,16383,1),(368,16383,2),(368,16383,6),(368,16383,7),(368,16383,8),(369,16383,1),(369,16383,2),(369,16383,6),(369,16383,7),(369,16383,8),(370,16383,1),(370,16383,2),(370,16383,6),(370,16383,7),(370,16383,8),(371,16383,1),(371,16383,2),(371,16383,6),(371,16383,7),(371,16383,8),(372,16383,1),(372,16383,2),(372,16383,6),(372,16383,7),(372,16383,8),(373,16383,1),(373,16383,2),(373,16383,6),(373,16383,7),(373,16383,8),(374,16383,1),(374,16383,2),(374,16383,6),(374,16383,7),(374,16383,8),(375,16383,1),(375,16383,2),(375,16383,6),(375,16383,7),(375,16383,8),(376,16383,1),(376,16383,2),(376,16383,6),(376,16383,7),(376,16383,8),(377,16383,1),(377,16383,2),(377,16383,6),(377,16383,7),(377,16383,8),(378,16383,1),(378,16383,2),(378,16383,6),(378,16383,7),(378,16383,8),(379,16383,1),(379,16383,2),(379,16383,6),(379,16383,7),(379,16383,8),(380,16383,1),(380,16383,2),(380,16383,6),(380,16383,7),(380,16383,8),(381,16383,1),(381,16383,2),(381,16383,6),(381,16383,7),(381,16383,8),(382,16383,1),(382,16383,2),(382,16383,6),(382,16383,7),(382,16383,8),(383,16383,1),(383,16383,2),(383,16383,6),(383,16383,7),(383,16383,8),(384,16383,1),(384,16383,2),(384,16383,6),(384,16383,7),(384,16383,8),(385,16383,1),(385,16383,2),(385,16383,6),(385,16383,7),(385,16383,8),(386,16383,1),(386,16383,2),(386,16383,6),(386,16383,7),(386,16383,8),(387,16383,1),(387,16383,2),(387,16383,6),(387,16383,7),(387,16383,8),(388,16383,1),(388,16383,2),(388,16383,6),(388,16383,7),(388,16383,8),(389,16383,1),(389,16383,2),(389,16383,6),(389,16383,7),(389,16383,8),(390,16383,1),(390,16383,2),(390,16383,6),(390,16383,7),(390,16383,8),(391,16383,1),(391,16383,2),(391,16383,6),(391,16383,7),(391,16383,8),(392,16383,1),(392,16383,2),(392,16383,6),(392,16383,7),(392,16383,8),(393,16383,1),(393,16383,2),(393,16383,6),(393,16383,7),(393,16383,8),(394,16383,1),(394,16383,2),(394,16383,6),(394,16383,7),(394,16383,8),(395,16383,1),(395,16383,2),(395,16383,6),(395,16383,7),(395,16383,8),(396,16383,1),(396,16383,2),(396,16383,6),(396,16383,7),(396,16383,8),(397,16383,1),(397,16383,2),(397,16383,6),(397,16383,7),(397,16383,8),(398,16383,1),(398,16383,2),(398,16383,6),(398,16383,7),(398,16383,8),(399,16383,1),(399,16383,2),(399,16383,6),(399,16383,7),(399,16383,8),(400,16383,1),(400,16383,2),(400,16383,6),(400,16383,7),(400,16383,8),(401,16383,1),(401,16383,2),(401,16383,6),(401,16383,7),(401,16383,8),(402,16383,1),(402,16383,2),(402,16383,6),(402,16383,7),(402,16383,8),(403,16383,1),(403,16383,2),(403,16383,6),(403,16383,7),(403,16383,8),(404,16383,1),(404,16383,2),(404,16383,6),(404,16383,7),(404,16383,8),(405,16383,1),(405,16383,2),(405,16383,6),(405,16383,7),(405,16383,8),(406,16383,1),(406,16383,2),(406,16383,6),(406,16383,7),(406,16383,8),(407,16383,1),(407,16383,2),(407,16383,6),(407,16383,7),(407,16383,8),(408,16383,1),(408,16383,2),(408,16383,6),(408,16383,7),(408,16383,8),(409,16383,1),(409,16383,2),(409,16383,6),(409,16383,7),(409,16383,8),(410,16383,1),(410,16383,2),(410,16383,6),(410,16383,7),(410,16383,8),(411,16383,1),(411,16383,2),(411,16383,6),(411,16383,7),(411,16383,8),(412,16383,1),(412,16383,2),(412,16383,6),(412,16383,7),(412,16383,8),(413,16383,1),(413,16383,2),(413,16383,6),(413,16383,7),(413,16383,8),(414,16383,1),(414,16383,2),(414,16383,6),(414,16383,7),(414,16383,8),(415,16383,1),(415,16383,2),(415,16383,6),(415,16383,7),(415,16383,8),(416,16383,1),(416,16383,2),(416,16383,6),(416,16383,7),(416,16383,8),(417,16383,1),(417,16383,2),(417,16383,6),(417,16383,7),(417,16383,8),(418,16383,1),(418,16383,2),(418,16383,6),(418,16383,7),(418,16383,8),(419,16383,1),(419,16383,2),(419,16383,6),(419,16383,7),(419,16383,8),(420,16383,1),(420,16383,2),(420,16383,6),(420,16383,7),(420,16383,8),(421,16383,1),(421,16383,2),(421,16383,6),(421,16383,7),(421,16383,8),(422,16383,1),(422,16383,2),(422,16383,6),(422,16383,7),(422,16383,8),(423,16383,1),(423,16383,2),(423,16383,6),(423,16383,7),(423,16383,8),(424,16383,1),(424,16383,2),(424,16383,6),(424,16383,7),(424,16383,8),(425,16383,1),(425,16383,2),(425,16383,6),(425,16383,7),(425,16383,8),(426,16383,1),(426,16383,2),(426,16383,6),(426,16383,7),(426,16383,8),(427,16383,1),(427,16383,2),(427,16383,6),(427,16383,7),(427,16383,8),(428,16383,1),(428,16383,2),(428,16383,6),(428,16383,7),(428,16383,8),(429,16383,1),(429,16383,2),(429,16383,6),(429,16383,7),(429,16383,8),(430,16383,1),(430,16383,2),(430,16383,6),(430,16383,7),(430,16383,8),(431,16383,1),(431,16383,2),(431,16383,6),(431,16383,7),(431,16383,8),(432,16383,1),(432,16383,2),(432,16383,6),(432,16383,7),(432,16383,8),(433,16383,1),(433,16383,2),(433,16383,6),(433,16383,7),(433,16383,8),(434,16383,1),(434,16383,2),(434,16383,6),(434,16383,7),(434,16383,8),(435,16383,1),(435,16383,2),(435,16383,6),(435,16383,7),(435,16383,8),(436,16383,1),(436,16383,2),(436,16383,6),(436,16383,7),(436,16383,8),(437,16383,1),(437,16383,2),(437,16383,6),(437,16383,7),(437,16383,8),(438,16383,1),(438,16383,2),(438,16383,6),(438,16383,7),(438,16383,8),(439,16383,1),(439,16383,2),(439,16383,6),(439,16383,7),(439,16383,8),(440,16383,1),(440,16383,2),(440,16383,6),(440,16383,7),(440,16383,8); +/*!40000 ALTER TABLE `acl2_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `admins` +-- + +DROP TABLE IF EXISTS `admins`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `admins` ( + `adminid` bigint(20) NOT NULL AUTO_INCREMENT, + `dn` varchar(255) NOT NULL, + `email_address` varchar(255) DEFAULT NULL, + `ca` smallint(6) NOT NULL, + PRIMARY KEY (`adminid`), + UNIQUE KEY `dn` (`dn`), + KEY `FKAB3A67047C6FEB32` (`ca`), + CONSTRAINT `FKAB3A67047C6FEB32` FOREIGN KEY (`ca`) REFERENCES `ca` (`cid`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `admins` +-- + +LOCK TABLES `admins` WRITE; +/*!40000 ALTER TABLE `admins` DISABLE KEYS */; +INSERT INTO `admins` VALUES (1,'/O=VOMS/O=System/CN=Internal VOMS Process',NULL,5),(2,'/O=VOMS/O=System/CN=Local Database Administrator',NULL,5),(3,'/O=VOMS/O=System/CN=Absolutely Anyone',NULL,5),(4,'/O=VOMS/O=System/CN=Any Authenticated User',NULL,5),(5,'/O=VOMS/O=System/CN=Unauthenticated Client',NULL,5),(6,'/test_0/Role=VO-Admin',NULL,7),(7,'/C=IT/O=IGI/CN=dev.local.io',NULL,3),(8,'/C=IT/O=IGI/CN=test0','andrea.ceccanti@cnaf.infn.it',3); +/*!40000 ALTER TABLE `admins` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `attributes` +-- + +DROP TABLE IF EXISTS `attributes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `attributes` ( + `a_id` bigint(20) NOT NULL AUTO_INCREMENT, + `a_desc` text, + `a_name` varchar(255) NOT NULL, + `a_uniq` bit(1) NOT NULL, + PRIMARY KEY (`a_id`), + UNIQUE KEY `a_name` (`a_name`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `attributes` +-- + +LOCK TABLES `attributes` WRITE; +/*!40000 ALTER TABLE `attributes` DISABLE KEYS */; +INSERT INTO `attributes` VALUES (1,'nickname','nickname','\0'),(2,'favourite_pet','favourite_pet','\0'),(3,'contagious_disease','contagious_disease','\0'); +/*!40000 ALTER TABLE `attributes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aup` +-- + +DROP TABLE IF EXISTS `aup`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aup` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `reacceptancePeriod` int(11) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `aup` +-- + +LOCK TABLES `aup` WRITE; +/*!40000 ALTER TABLE `aup` DISABLE KEYS */; +INSERT INTO `aup` VALUES (1,'VO-AUP','',365); +/*!40000 ALTER TABLE `aup` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aup_acc_record` +-- + +DROP TABLE IF EXISTS `aup_acc_record`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aup_acc_record` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `aup_version_id` bigint(20) NOT NULL, + `usr_id` bigint(20) NOT NULL, + `last_acceptance_date` datetime NOT NULL, + `valid` bit(1) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `aup_version_id` (`aup_version_id`,`usr_id`), + KEY `FKB1979B32EE2D4487` (`usr_id`), + KEY `FKB1979B32815F1678` (`aup_version_id`), + CONSTRAINT `FKB1979B32815F1678` FOREIGN KEY (`aup_version_id`) REFERENCES `aup_version` (`id`), + CONSTRAINT `FKB1979B32EE2D4487` FOREIGN KEY (`usr_id`) REFERENCES `usr` (`userid`) +) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `aup_acc_record` +-- + +LOCK TABLES `aup_acc_record` WRITE; +/*!40000 ALTER TABLE `aup_acc_record` DISABLE KEYS */; +INSERT INTO `aup_acc_record` VALUES (1,1,1,'2017-03-21 17:49:50',''),(2,1,2,'2017-03-21 17:49:50',''),(3,1,3,'2017-03-21 17:49:51',''),(4,1,4,'2017-03-21 17:49:52',''),(5,1,5,'2017-03-21 17:49:52',''),(6,1,6,'2017-03-21 17:49:53',''),(7,1,7,'2017-03-21 17:49:53',''),(8,1,8,'2017-03-21 17:49:54',''),(9,1,9,'2017-03-21 17:49:55',''),(10,1,10,'2017-03-21 17:49:55',''),(11,1,11,'2017-03-21 17:49:55',''),(12,1,12,'2017-03-21 17:49:56',''),(13,1,13,'2017-03-21 17:49:56',''),(14,1,14,'2017-03-21 17:49:57',''),(15,1,15,'2017-03-21 17:49:57',''),(16,1,16,'2017-03-21 17:49:57',''),(17,1,17,'2017-03-21 17:49:58',''),(18,1,18,'2017-03-21 17:49:58',''),(19,1,19,'2017-03-21 17:49:59',''),(20,1,20,'2017-03-21 17:49:59',''),(21,1,21,'2017-03-21 17:50:00',''),(22,1,22,'2017-03-21 17:50:00',''),(23,1,23,'2017-03-21 17:50:01',''),(24,1,24,'2017-03-21 17:50:01',''),(25,1,25,'2017-03-21 17:50:02',''),(26,1,26,'2017-03-21 17:50:02',''),(27,1,27,'2017-03-21 17:50:03',''),(28,1,28,'2017-03-21 17:50:03',''),(29,1,29,'2017-03-21 17:50:04',''),(30,1,30,'2017-03-21 17:50:04',''),(31,1,31,'2017-03-21 17:50:04',''),(32,1,32,'2017-03-21 17:50:05',''),(33,1,33,'2017-03-21 17:50:05',''),(34,1,34,'2017-03-21 17:50:05',''),(35,1,35,'2017-03-21 17:50:06',''),(36,1,36,'2017-03-21 17:50:07',''),(37,1,37,'2017-03-21 17:50:08',''),(38,1,38,'2017-03-21 17:50:08',''),(39,1,39,'2017-03-21 17:50:08',''),(40,1,40,'2017-03-21 17:50:09',''),(41,1,41,'2017-03-21 17:50:09',''),(42,1,42,'2017-03-21 17:50:10',''),(43,1,43,'2017-03-21 17:50:10',''),(44,1,44,'2017-03-21 17:50:11',''),(45,1,45,'2017-03-21 17:50:11',''),(46,1,46,'2017-03-21 17:50:11',''),(47,1,47,'2017-03-21 17:50:12',''),(48,1,48,'2017-03-21 17:50:12',''),(49,1,49,'2017-03-21 17:50:12',''),(50,1,50,'2017-03-21 17:50:13',''),(51,1,51,'2017-03-21 17:50:13',''),(52,1,52,'2017-03-21 17:50:14',''),(53,1,53,'2017-03-21 17:50:14',''),(54,1,54,'2017-03-21 17:50:15',''),(55,1,55,'2017-03-21 17:50:15',''),(56,1,56,'2017-03-21 17:50:15',''),(57,1,57,'2017-03-21 17:50:16',''),(58,1,58,'2017-03-21 17:50:16',''),(59,1,59,'2017-03-21 17:50:16',''),(60,1,60,'2017-03-21 17:50:17',''),(61,1,61,'2017-03-21 17:50:17',''),(62,1,62,'2017-03-21 17:50:17',''),(63,1,63,'2017-03-21 17:50:18',''),(64,1,64,'2017-03-21 17:50:18',''),(65,1,65,'2017-03-21 17:50:19',''),(66,1,66,'2017-03-21 17:50:19',''),(67,1,67,'2017-03-21 17:50:20',''),(68,1,68,'2017-03-21 17:50:21',''),(69,1,69,'2017-03-21 17:50:21',''),(70,1,70,'2017-03-21 17:50:22',''),(71,1,71,'2017-03-21 17:50:22',''),(72,1,72,'2017-03-21 17:50:23',''),(73,1,73,'2017-03-21 17:50:23',''),(74,1,74,'2017-03-21 17:50:24',''),(75,1,75,'2017-03-21 17:50:24',''),(76,1,76,'2017-03-21 17:50:24',''),(77,1,77,'2017-03-21 17:50:25',''),(78,1,78,'2017-03-21 17:50:25',''),(79,1,79,'2017-03-21 17:50:26',''),(80,1,80,'2017-03-21 17:50:26',''),(81,1,81,'2017-03-21 17:50:26',''),(82,1,82,'2017-03-21 17:50:27',''),(83,1,83,'2017-03-21 17:50:27',''),(84,1,84,'2017-03-21 17:50:28',''),(85,1,85,'2017-03-21 17:50:29',''),(86,1,86,'2017-03-21 17:50:29',''),(87,1,87,'2017-03-21 17:50:30',''),(88,1,88,'2017-03-21 17:50:30',''),(89,1,89,'2017-03-21 17:50:30',''),(90,1,90,'2017-03-21 17:50:31',''),(91,1,91,'2017-03-21 17:50:31',''),(92,1,92,'2017-03-21 17:50:32',''),(93,1,93,'2017-03-21 17:50:32',''),(94,1,94,'2017-03-21 17:50:32',''),(95,1,95,'2017-03-21 17:50:33',''),(96,1,96,'2017-03-21 17:50:33',''),(97,1,97,'2017-03-21 17:50:34',''),(98,1,98,'2017-03-21 17:50:34',''),(99,1,99,'2017-03-21 17:50:34',''),(100,1,100,'2017-03-21 17:50:35',''),(101,1,101,'2017-03-21 17:50:35',''),(102,1,102,'2017-03-21 17:50:36',''),(103,1,103,'2017-03-21 17:50:36',''),(104,1,104,'2017-03-21 17:50:37',''),(105,1,105,'2017-03-21 17:50:38',''),(106,1,106,'2017-03-21 17:50:38',''),(107,1,107,'2017-03-21 17:50:39',''),(108,1,108,'2017-03-21 17:50:39',''),(109,1,109,'2017-03-21 17:50:39',''),(110,1,110,'2017-03-21 17:50:40',''),(111,1,111,'2017-03-21 17:50:40',''),(112,1,112,'2017-03-21 17:50:41',''),(113,1,113,'2017-03-21 17:50:41',''),(114,1,114,'2017-03-21 17:50:41',''),(115,1,115,'2017-03-21 17:50:42',''),(116,1,116,'2017-03-21 17:50:42',''),(117,1,117,'2017-03-21 17:50:43',''),(118,1,118,'2017-03-21 17:50:43',''),(119,1,119,'2017-03-21 17:50:43',''),(120,1,120,'2017-03-21 17:50:44',''),(121,1,121,'2017-03-21 17:50:44',''),(122,1,122,'2017-03-21 17:50:45',''),(123,1,123,'2017-03-21 17:50:45',''),(124,1,124,'2017-03-21 17:50:46',''),(125,1,125,'2017-03-21 17:50:46',''),(126,1,126,'2017-03-21 17:50:47',''),(127,1,127,'2017-03-21 17:50:47',''),(128,1,128,'2017-03-21 17:50:48',''),(129,1,129,'2017-03-21 17:50:49',''),(130,1,130,'2017-03-21 17:50:49',''),(131,1,131,'2017-03-21 17:50:49',''),(132,1,132,'2017-03-21 17:50:50',''),(133,1,133,'2017-03-21 17:50:50',''),(134,1,134,'2017-03-21 17:50:50',''),(135,1,135,'2017-03-21 17:50:51',''),(136,1,136,'2017-03-21 17:50:51',''),(137,1,137,'2017-03-21 17:50:52',''),(138,1,138,'2017-03-21 17:50:52',''),(139,1,139,'2017-03-21 17:50:53',''),(140,1,140,'2017-03-21 17:50:53',''),(141,1,141,'2017-03-21 17:50:53',''),(142,1,142,'2017-03-21 17:50:54',''),(143,1,143,'2017-03-21 17:50:54',''),(144,1,144,'2017-03-21 17:50:54',''),(145,1,145,'2017-03-21 17:50:55',''),(146,1,146,'2017-03-21 17:50:55',''),(147,1,147,'2017-03-21 17:50:55',''),(148,1,148,'2017-03-21 17:50:56',''),(149,1,149,'2017-03-21 17:50:56',''),(150,1,150,'2017-03-21 17:50:56',''),(151,1,151,'2017-03-21 17:50:57',''),(152,1,152,'2017-03-21 17:50:57',''),(153,1,153,'2017-03-21 17:50:58',''),(154,1,154,'2017-03-21 17:50:58',''),(155,1,155,'2017-03-21 17:50:58',''),(156,1,156,'2017-03-21 17:50:59',''),(157,1,157,'2017-03-21 17:50:59',''),(158,1,158,'2017-03-21 17:50:59',''),(159,1,159,'2017-03-21 17:51:00',''),(160,1,160,'2017-03-21 17:51:00',''),(161,1,161,'2017-03-21 17:51:00',''),(162,1,162,'2017-03-21 17:51:01',''),(163,1,163,'2017-03-21 17:51:01',''),(164,1,164,'2017-03-21 17:51:02',''),(165,1,165,'2017-03-21 17:51:02',''),(166,1,166,'2017-03-21 17:51:02',''),(167,1,167,'2017-03-21 17:51:03',''),(168,1,168,'2017-03-21 17:51:03',''),(169,1,169,'2017-03-21 17:51:04',''),(170,1,170,'2017-03-21 17:51:04',''),(171,1,171,'2017-03-21 17:51:04',''),(172,1,172,'2017-03-21 17:51:05',''),(173,1,173,'2017-03-21 17:51:05',''),(174,1,174,'2017-03-21 17:51:05',''),(175,1,175,'2017-03-21 17:51:06',''),(176,1,176,'2017-03-21 17:51:06',''),(177,1,177,'2017-03-21 17:51:06',''),(178,1,178,'2017-03-21 17:51:07',''),(179,1,179,'2017-03-21 17:51:08',''),(180,1,180,'2017-03-21 17:51:08',''),(181,1,181,'2017-03-21 17:51:09',''),(182,1,182,'2017-03-21 17:51:09',''),(183,1,183,'2017-03-21 17:51:10',''),(184,1,184,'2017-03-21 17:51:10',''),(185,1,185,'2017-03-21 17:51:11',''),(186,1,186,'2017-03-21 17:51:11',''),(187,1,187,'2017-03-21 17:51:11',''),(188,1,188,'2017-03-21 17:51:12',''),(189,1,189,'2017-03-21 17:51:12',''),(190,1,190,'2017-03-21 17:51:12',''),(191,1,191,'2017-03-21 17:51:13',''),(192,1,192,'2017-03-21 17:51:13',''),(193,1,193,'2017-03-21 17:51:14',''),(194,1,194,'2017-03-21 17:51:14',''),(195,1,195,'2017-03-21 17:51:15',''),(196,1,196,'2017-03-21 17:51:15',''),(197,1,197,'2017-03-21 17:51:15',''),(198,1,198,'2017-03-21 17:51:16',''),(199,1,199,'2017-03-21 17:51:16',''),(200,1,200,'2017-03-21 17:51:16',''); +/*!40000 ALTER TABLE `aup_acc_record` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `aup_version` +-- + +DROP TABLE IF EXISTS `aup_version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `aup_version` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `aup_id` bigint(20) NOT NULL, + `version` varchar(255) NOT NULL, + `url` varchar(255) DEFAULT NULL, + `text` varchar(255) DEFAULT NULL, + `creationTime` datetime NOT NULL, + `lastForcedReacceptanceTime` datetime DEFAULT NULL, + `active` bit(1) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `aup_id` (`aup_id`,`version`), + KEY `fk_aup_version_aup` (`aup_id`), + CONSTRAINT `fk_aup_version_aup` FOREIGN KEY (`aup_id`) REFERENCES `aup` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `aup_version` +-- + +LOCK TABLES `aup_version` WRITE; +/*!40000 ALTER TABLE `aup_version` DISABLE KEYS */; +INSERT INTO `aup_version` VALUES (1,1,'1.0','file:/etc/voms-admin/test_0/vo-aup.txt',NULL,'2017-03-21 17:47:27',NULL,''); +/*!40000 ALTER TABLE `aup_version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `ca` +-- + +DROP TABLE IF EXISTS `ca`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `ca` ( + `cid` smallint(6) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `description` varchar(255) DEFAULT NULL, + `subject_string` varchar(255) NOT NULL, + PRIMARY KEY (`cid`), + UNIQUE KEY `subject_string` (`subject_string`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `ca` +-- + +LOCK TABLES `ca` WRITE; +/*!40000 ALTER TABLE `ca` DISABLE KEYS */; +INSERT INTO `ca` VALUES (1,'2017-03-21 17:47:27',NULL,'/C=IT/O=INFN/CN=INFN Certification Authority'),(2,'2017-03-21 17:47:27',NULL,'/C=IT/O=IGI/CN=Test CA 2'),(3,'2017-03-21 17:47:27',NULL,'/C=IT/O=IGI/CN=Test CA'),(4,'2017-03-21 17:47:27',NULL,'/C=IT/O=IGI/CN=Test CA (SHA 256)'),(5,'2017-03-21 17:47:27','A dummy CA for local org.glite.security.voms.admin.persistence.error mainteneance','/O=VOMS/O=System/CN=Dummy Certificate Authority'),(6,'2017-03-21 17:47:27','A virtual CA for VOMS groups.','/O=VOMS/O=System/CN=VOMS Group'),(7,'2017-03-21 17:47:27','A virtual CA for VOMS roles.','/O=VOMS/O=System/CN=VOMS Role'),(8,'2017-03-21 17:47:27','A virtual CA for authz manager attributes','/O=VOMS/O=System/CN=Authorization Manager Attributes'); +/*!40000 ALTER TABLE `ca` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `certificate` +-- + +DROP TABLE IF EXISTS `certificate`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `certificate` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `creation_time` datetime NOT NULL, + `subject_string` varchar(255) NOT NULL, + `suspended` bit(1) NOT NULL, + `suspended_reason` varchar(255) DEFAULT NULL, + `suspension_reason_code` varchar(255) DEFAULT NULL, + `ca_id` smallint(6) NOT NULL, + `usr_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ca_id` (`ca_id`,`subject_string`), + KEY `FK745F4197EE2D4487` (`usr_id`), + KEY `FK745F419782107F70` (`ca_id`), + CONSTRAINT `FK745F419782107F70` FOREIGN KEY (`ca_id`) REFERENCES `ca` (`cid`), + CONSTRAINT `FK745F4197EE2D4487` FOREIGN KEY (`usr_id`) REFERENCES `usr` (`userid`) +) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `certificate` +-- + +LOCK TABLES `certificate` WRITE; +/*!40000 ALTER TABLE `certificate` DISABLE KEYS */; +INSERT INTO `certificate` VALUES (1,'2017-03-21 17:49:50','/C=IT/O=IGI/CN=CONRAD BASSETTE','\0',NULL,NULL,3,1),(2,'2017-03-21 17:49:50','/C=IT/O=IGI/CN=MICHAELA MCPHERREN','\0',NULL,NULL,3,2),(3,'2017-03-21 17:49:51','/C=IT/O=IGI/CN=TINY KABLER','\0',NULL,NULL,3,3),(4,'2017-03-21 17:49:52','/C=IT/O=IGI/CN=HAI JACOBOVITS','\0',NULL,NULL,3,4),(5,'2017-03-21 17:49:52','/C=IT/O=IGI/CN=MCKENZIE DELANG','\0',NULL,NULL,3,5),(6,'2017-03-21 17:49:53','/C=IT/O=IGI/CN=CECILY ANDERTON','\0',NULL,NULL,3,6),(7,'2017-03-21 17:49:53','/C=IT/O=IGI/CN=LATESHA SPINOZA','\0',NULL,NULL,3,7),(8,'2017-03-21 17:49:54','/C=IT/O=IGI/CN=SHAQUANA KONON','\0',NULL,NULL,3,8),(9,'2017-03-21 17:49:55','/C=IT/O=IGI/CN=DANNIE WALSH','\0',NULL,NULL,3,9),(10,'2017-03-21 17:49:55','/C=IT/O=IGI/CN=EUNICE ORLEANS','\0',NULL,NULL,3,10),(11,'2017-03-21 17:49:55','/C=IT/O=IGI/CN=LAHOMA PRESTINO','\0',NULL,NULL,3,11),(12,'2017-03-21 17:49:56','/C=IT/O=IGI/CN=DOREEN BOURDEAU','\0',NULL,NULL,3,12),(13,'2017-03-21 17:49:56','/C=IT/O=IGI/CN=WAI PINKERTON','\0',NULL,NULL,3,13),(14,'2017-03-21 17:49:57','/C=IT/O=IGI/CN=KACY COLLICA','\0',NULL,NULL,3,14),(15,'2017-03-21 17:49:57','/C=IT/O=IGI/CN=ADINA PIERETTI','\0',NULL,NULL,3,15),(16,'2017-03-21 17:49:57','/C=IT/O=IGI/CN=ANTHONY ELNICKI','\0',NULL,NULL,3,16),(17,'2017-03-21 17:49:58','/C=IT/O=IGI/CN=ERIC RADWAN','\0',NULL,NULL,3,17),(18,'2017-03-21 17:49:58','/C=IT/O=IGI/CN=MARX DALMATA','\0',NULL,NULL,3,18),(19,'2017-03-21 17:49:59','/C=IT/O=IGI/CN=MADALINE SHERROD','\0',NULL,NULL,3,19),(20,'2017-03-21 17:49:59','/C=IT/O=IGI/CN=ABEL BURBACK','\0',NULL,NULL,3,20),(21,'2017-03-21 17:50:00','/C=IT/O=IGI/CN=CALLIE NAGINDAS','\0',NULL,NULL,3,21),(22,'2017-03-21 17:50:00','/C=IT/O=IGI/CN=ABE LERWILL','\0',NULL,NULL,3,22),(23,'2017-03-21 17:50:01','/C=IT/O=IGI/CN=LOUIS WHITELIGHTNIN','\0',NULL,NULL,3,23),(24,'2017-03-21 17:50:01','/C=IT/O=IGI/CN=SHAWNNA LANGLINAIS','\0',NULL,NULL,3,24),(25,'2017-03-21 17:50:02','/C=IT/O=IGI/CN=CHAD CAVALIERO','\0',NULL,NULL,3,25),(26,'2017-03-21 17:50:02','/C=IT/O=IGI/CN=LAKEISHA MCMORRIS','\0',NULL,NULL,3,26),(27,'2017-03-21 17:50:03','/C=IT/O=IGI/CN=RODNEY HACHER','\0',NULL,NULL,3,27),(28,'2017-03-21 17:50:03','/C=IT/O=IGI/CN=CARLA DAEHN','\0',NULL,NULL,3,28),(29,'2017-03-21 17:50:04','/C=IT/O=IGI/CN=MARLON KRUPPENBACHER','\0',NULL,NULL,3,29),(30,'2017-03-21 17:50:04','/C=IT/O=IGI/CN=VERTIE STAMER','\0',NULL,NULL,3,30),(31,'2017-03-21 17:50:04','/C=IT/O=IGI/CN=DELLA BARKLOW','\0',NULL,NULL,3,31),(32,'2017-03-21 17:50:05','/C=IT/O=IGI/CN=CECILIA LALL','\0',NULL,NULL,3,32),(33,'2017-03-21 17:50:05','/C=IT/O=IGI/CN=TIERA DOWLIN','\0',NULL,NULL,3,33),(34,'2017-03-21 17:50:05','/C=IT/O=IGI/CN=DETRA TATAR','\0',NULL,NULL,3,34),(35,'2017-03-21 17:50:06','/C=IT/O=IGI/CN=JULES TOTTEN','\0',NULL,NULL,3,35),(36,'2017-03-21 17:50:07','/C=IT/O=IGI/CN=DORTHA HOBDAY','\0',NULL,NULL,3,36),(37,'2017-03-21 17:50:08','/C=IT/O=IGI/CN=BERENICE ORLOWSKY','\0',NULL,NULL,3,37),(38,'2017-03-21 17:50:08','/C=IT/O=IGI/CN=BRITTANEY DENIER','\0',NULL,NULL,3,38),(39,'2017-03-21 17:50:08','/C=IT/O=IGI/CN=ALITA HONTZ','\0',NULL,NULL,3,39),(40,'2017-03-21 17:50:09','/C=IT/O=IGI/CN=FREEMAN KOBIE','\0',NULL,NULL,3,40),(41,'2017-03-21 17:50:09','/C=IT/O=IGI/CN=LEEANNA VOIGT','\0',NULL,NULL,3,41),(42,'2017-03-21 17:50:10','/C=IT/O=IGI/CN=JOSH PAULINA','\0',NULL,NULL,3,42),(43,'2017-03-21 17:50:10','/C=IT/O=IGI/CN=DACIA SHAUB','\0',NULL,NULL,3,43),(44,'2017-03-21 17:50:11','/C=IT/O=IGI/CN=FREDERICK WIRTA','\0',NULL,NULL,3,44),(45,'2017-03-21 17:50:11','/C=IT/O=IGI/CN=TRICIA WIESER','\0',NULL,NULL,3,45),(46,'2017-03-21 17:50:11','/C=IT/O=IGI/CN=ELIN GOSTOMSKI','\0',NULL,NULL,3,46),(47,'2017-03-21 17:50:12','/C=IT/O=IGI/CN=FREDRICK LINNELL','\0',NULL,NULL,3,47),(48,'2017-03-21 17:50:12','/C=IT/O=IGI/CN=LYNN RIGHTMYER','\0',NULL,NULL,3,48),(49,'2017-03-21 17:50:12','/C=IT/O=IGI/CN=SIMA WEST','\0',NULL,NULL,3,49),(50,'2017-03-21 17:50:13','/C=IT/O=IGI/CN=YUKIKO DONOHO','\0',NULL,NULL,3,50),(51,'2017-03-21 17:50:13','/C=IT/O=IGI/CN=LASHONDA WESTHOUSE','\0',NULL,NULL,3,51),(52,'2017-03-21 17:50:14','/C=IT/O=IGI/CN=CARMON PARLOR','\0',NULL,NULL,3,52),(53,'2017-03-21 17:50:14','/C=IT/O=IGI/CN=BESS SWETT','\0',NULL,NULL,3,53),(54,'2017-03-21 17:50:14','/C=IT/O=IGI/CN=JACKSON LEDDON','\0',NULL,NULL,3,54),(55,'2017-03-21 17:50:15','/C=IT/O=IGI/CN=GENNA HANISKO','\0',NULL,NULL,3,55),(56,'2017-03-21 17:50:15','/C=IT/O=IGI/CN=JUDIE WICKINGS','\0',NULL,NULL,3,56),(57,'2017-03-21 17:50:16','/C=IT/O=IGI/CN=KATHLENE SCHNECKLOTH','\0',NULL,NULL,3,57),(58,'2017-03-21 17:50:16','/C=IT/O=IGI/CN=OTIS TOPLK','\0',NULL,NULL,3,58),(59,'2017-03-21 17:50:16','/C=IT/O=IGI/CN=BERNARDO DEISHER','\0',NULL,NULL,3,59),(60,'2017-03-21 17:50:17','/C=IT/O=IGI/CN=LIZ WILCINSKI','\0',NULL,NULL,3,60),(61,'2017-03-21 17:50:17','/C=IT/O=IGI/CN=CHU KURLAND','\0',NULL,NULL,3,61),(62,'2017-03-21 17:50:17','/C=IT/O=IGI/CN=VAL KAUFFMANN','\0',NULL,NULL,3,62),(63,'2017-03-21 17:50:18','/C=IT/O=IGI/CN=JOEY FREIMUTH','\0',NULL,NULL,3,63),(64,'2017-03-21 17:50:18','/C=IT/O=IGI/CN=CHANCE BARRO','\0',NULL,NULL,3,64),(65,'2017-03-21 17:50:19','/C=IT/O=IGI/CN=VI SZWARC','\0',NULL,NULL,3,65),(66,'2017-03-21 17:50:19','/C=IT/O=IGI/CN=CARITA ABT','\0',NULL,NULL,3,66),(67,'2017-03-21 17:50:20','/C=IT/O=IGI/CN=COURTNEY VEIGEL','\0',NULL,NULL,3,67),(68,'2017-03-21 17:50:21','/C=IT/O=IGI/CN=ALDA MANGUS','\0',NULL,NULL,3,68),(69,'2017-03-21 17:50:21','/C=IT/O=IGI/CN=BERTHA MAUFFRAY','\0',NULL,NULL,3,69),(70,'2017-03-21 17:50:22','/C=IT/O=IGI/CN=PAULITA DOSTIE','\0',NULL,NULL,3,70),(71,'2017-03-21 17:50:22','/C=IT/O=IGI/CN=NELLIE BURKHARD','\0',NULL,NULL,3,71),(72,'2017-03-21 17:50:23','/C=IT/O=IGI/CN=XOCHITL FELLEMAN','\0',NULL,NULL,3,72),(73,'2017-03-21 17:50:23','/C=IT/O=IGI/CN=KEN OBRADOVICH','\0',NULL,NULL,3,73),(74,'2017-03-21 17:50:24','/C=IT/O=IGI/CN=WANITA DARRAH','\0',NULL,NULL,3,74),(75,'2017-03-21 17:50:24','/C=IT/O=IGI/CN=WILHELMINA MONARREZ','\0',NULL,NULL,3,75),(76,'2017-03-21 17:50:24','/C=IT/O=IGI/CN=LETA STENBERG','\0',NULL,NULL,3,76),(77,'2017-03-21 17:50:25','/C=IT/O=IGI/CN=BERT DEODATO','\0',NULL,NULL,3,77),(78,'2017-03-21 17:50:25','/C=IT/O=IGI/CN=IRMA LANOIE','\0',NULL,NULL,3,78),(79,'2017-03-21 17:50:26','/C=IT/O=IGI/CN=OTIS FLATTERY','\0',NULL,NULL,3,79),(80,'2017-03-21 17:50:26','/C=IT/O=IGI/CN=NOBUKO LAITE','\0',NULL,NULL,3,80),(81,'2017-03-21 17:50:26','/C=IT/O=IGI/CN=JED CATTS','\0',NULL,NULL,3,81),(82,'2017-03-21 17:50:27','/C=IT/O=IGI/CN=PAUL BOHLER','\0',NULL,NULL,3,82),(83,'2017-03-21 17:50:27','/C=IT/O=IGI/CN=CHANCE SAVEL','\0',NULL,NULL,3,83),(84,'2017-03-21 17:50:28','/C=IT/O=IGI/CN=TIJUANA CABBLE','\0',NULL,NULL,3,84),(85,'2017-03-21 17:50:29','/C=IT/O=IGI/CN=AZZIE TORELLI','\0',NULL,NULL,3,85),(86,'2017-03-21 17:50:29','/C=IT/O=IGI/CN=CARYLON VERSTRAETE','\0',NULL,NULL,3,86),(87,'2017-03-21 17:50:30','/C=IT/O=IGI/CN=WAVA BENKEN','\0',NULL,NULL,3,87),(88,'2017-03-21 17:50:30','/C=IT/O=IGI/CN=VENNIE DOMENICK','\0',NULL,NULL,3,88),(89,'2017-03-21 17:50:30','/C=IT/O=IGI/CN=FREDDA HYTEN','\0',NULL,NULL,3,89),(90,'2017-03-21 17:50:31','/C=IT/O=IGI/CN=HAYDEE BZHYAN','\0',NULL,NULL,3,90),(91,'2017-03-21 17:50:31','/C=IT/O=IGI/CN=ELIJAH BURDELL','\0',NULL,NULL,3,91),(92,'2017-03-21 17:50:32','/C=IT/O=IGI/CN=BETHANIE CASTILLA','\0',NULL,NULL,3,92),(93,'2017-03-21 17:50:32','/C=IT/O=IGI/CN=LESLIE HANCOCK','\0',NULL,NULL,3,93),(94,'2017-03-21 17:50:32','/C=IT/O=IGI/CN=XENIA HAULBROOK','\0',NULL,NULL,3,94),(95,'2017-03-21 17:50:33','/C=IT/O=IGI/CN=YUKO CROMBIE','\0',NULL,NULL,3,95),(96,'2017-03-21 17:50:33','/C=IT/O=IGI/CN=JALEESA HANIFAN','\0',NULL,NULL,3,96),(97,'2017-03-21 17:50:34','/C=IT/O=IGI/CN=KRYSTIN LYBRAND','\0',NULL,NULL,3,97),(98,'2017-03-21 17:50:34','/C=IT/O=IGI/CN=KORY MCPARLAND','\0',NULL,NULL,3,98),(99,'2017-03-21 17:50:34','/C=IT/O=IGI/CN=WAN SAMMON','\0',NULL,NULL,3,99),(100,'2017-03-21 17:50:35','/C=IT/O=IGI/CN=HANH ATCITTY','\0',NULL,NULL,3,100),(101,'2017-03-21 17:50:35','/C=IT/O=IGI/CN=ANGELIC URBINA','\0',NULL,NULL,3,101),(102,'2017-03-21 17:50:36','/C=IT/O=IGI/CN=AUSTIN CARABAJAL','\0',NULL,NULL,3,102),(103,'2017-03-21 17:50:36','/C=IT/O=IGI/CN=INGA DINGFELDER','\0',NULL,NULL,3,103),(104,'2017-03-21 17:50:37','/C=IT/O=IGI/CN=LIVIA ASHBACHER','\0',NULL,NULL,3,104),(105,'2017-03-21 17:50:38','/C=IT/O=IGI/CN=BROOKE LEBEDEFF','\0',NULL,NULL,3,105),(106,'2017-03-21 17:50:38','/C=IT/O=IGI/CN=SUNSHINE BUTTARO','\0',NULL,NULL,3,106),(107,'2017-03-21 17:50:39','/C=IT/O=IGI/CN=TWYLA TIBWELL','\0',NULL,NULL,3,107),(108,'2017-03-21 17:50:39','/C=IT/O=IGI/CN=MILLARD CARAVELLA','\0',NULL,NULL,3,108),(109,'2017-03-21 17:50:39','/C=IT/O=IGI/CN=MARGURITE AYOOB','\0',NULL,NULL,3,109),(110,'2017-03-21 17:50:40','/C=IT/O=IGI/CN=MARIKO TENN','\0',NULL,NULL,3,110),(111,'2017-03-21 17:50:40','/C=IT/O=IGI/CN=JINNY KRUGER','\0',NULL,NULL,3,111),(112,'2017-03-21 17:50:41','/C=IT/O=IGI/CN=RETHA PINCHBECK','\0',NULL,NULL,3,112),(113,'2017-03-21 17:50:41','/C=IT/O=IGI/CN=KIMBERY LOBDELL','\0',NULL,NULL,3,113),(114,'2017-03-21 17:50:41','/C=IT/O=IGI/CN=SHIRELY BORGATTI','\0',NULL,NULL,3,114),(115,'2017-03-21 17:50:42','/C=IT/O=IGI/CN=TODD OKKEN','\0',NULL,NULL,3,115),(116,'2017-03-21 17:50:42','/C=IT/O=IGI/CN=RUPERT MONTALBO','\0',NULL,NULL,3,116),(117,'2017-03-21 17:50:43','/C=IT/O=IGI/CN=JIMMIE ISRAELSEN','\0',NULL,NULL,3,117),(118,'2017-03-21 17:50:43','/C=IT/O=IGI/CN=STEPANIE VOLNER','\0',NULL,NULL,3,118),(119,'2017-03-21 17:50:43','/C=IT/O=IGI/CN=ULRIKE KEMPSON','\0',NULL,NULL,3,119),(120,'2017-03-21 17:50:44','/C=IT/O=IGI/CN=JINA MEGO','\0',NULL,NULL,3,120),(121,'2017-03-21 17:50:44','/C=IT/O=IGI/CN=VANNA JOOS','\0',NULL,NULL,3,121),(122,'2017-03-21 17:50:45','/C=IT/O=IGI/CN=TONA RAROGAL','\0',NULL,NULL,3,122),(123,'2017-03-21 17:50:45','/C=IT/O=IGI/CN=BRYAN HEMERLY','\0',NULL,NULL,3,123),(124,'2017-03-21 17:50:46','/C=IT/O=IGI/CN=ALEEN DARCO','\0',NULL,NULL,3,124),(125,'2017-03-21 17:50:46','/C=IT/O=IGI/CN=MARGUERITE MITCHLER','\0',NULL,NULL,3,125),(126,'2017-03-21 17:50:47','/C=IT/O=IGI/CN=ELLENA BEICHNER','\0',NULL,NULL,3,126),(127,'2017-03-21 17:50:47','/C=IT/O=IGI/CN=PEGGY DATY','\0',NULL,NULL,3,127),(128,'2017-03-21 17:50:48','/C=IT/O=IGI/CN=ELNORA HOMBY','\0',NULL,NULL,3,128),(129,'2017-03-21 17:50:49','/C=IT/O=IGI/CN=DREAMA LUCKENBAUGH','\0',NULL,NULL,3,129),(130,'2017-03-21 17:50:49','/C=IT/O=IGI/CN=HORTENCIA TICA','\0',NULL,NULL,3,130),(131,'2017-03-21 17:50:49','/C=IT/O=IGI/CN=OTTO BEUMER','\0',NULL,NULL,3,131),(132,'2017-03-21 17:50:50','/C=IT/O=IGI/CN=ZACHARY BIHM','\0',NULL,NULL,3,132),(133,'2017-03-21 17:50:50','/C=IT/O=IGI/CN=ANNMARIE MUSILLI','\0',NULL,NULL,3,133),(134,'2017-03-21 17:50:50','/C=IT/O=IGI/CN=SAL LUTGEN','\0',NULL,NULL,3,134),(135,'2017-03-21 17:50:51','/C=IT/O=IGI/CN=DAMON HUMMINGBIRD','\0',NULL,NULL,3,135),(136,'2017-03-21 17:50:51','/C=IT/O=IGI/CN=GRACIE PADIONG','\0',NULL,NULL,3,136),(137,'2017-03-21 17:50:52','/C=IT/O=IGI/CN=MARSHALL PORTEUS','\0',NULL,NULL,3,137),(138,'2017-03-21 17:50:52','/C=IT/O=IGI/CN=ISIDRA CLAP','\0',NULL,NULL,3,138),(139,'2017-03-21 17:50:53','/C=IT/O=IGI/CN=CHUNG PONTONIO','\0',NULL,NULL,3,139),(140,'2017-03-21 17:50:53','/C=IT/O=IGI/CN=CLAUDIA GRAYSON','\0',NULL,NULL,3,140),(141,'2017-03-21 17:50:53','/C=IT/O=IGI/CN=JONELL POWROZNIK','\0',NULL,NULL,3,141),(142,'2017-03-21 17:50:54','/C=IT/O=IGI/CN=KIMBERLEE BRUMMET','\0',NULL,NULL,3,142),(143,'2017-03-21 17:50:54','/C=IT/O=IGI/CN=JEWELL DELSORDO','\0',NULL,NULL,3,143),(144,'2017-03-21 17:50:54','/C=IT/O=IGI/CN=FERMINA WHITNER','\0',NULL,NULL,3,144),(145,'2017-03-21 17:50:55','/C=IT/O=IGI/CN=MARTHA HOLLMANN','\0',NULL,NULL,3,145),(146,'2017-03-21 17:50:55','/C=IT/O=IGI/CN=DEIDRE HINGSTON','\0',NULL,NULL,3,146),(147,'2017-03-21 17:50:55','/C=IT/O=IGI/CN=DEWITT MOHLKE','\0',NULL,NULL,3,147),(148,'2017-03-21 17:50:56','/C=IT/O=IGI/CN=PETRONILA ALSANDOR','\0',NULL,NULL,3,148),(149,'2017-03-21 17:50:56','/C=IT/O=IGI/CN=TERI GRECH','\0',NULL,NULL,3,149),(150,'2017-03-21 17:50:56','/C=IT/O=IGI/CN=CLINT GOLUB','\0',NULL,NULL,3,150),(151,'2017-03-21 17:50:57','/C=IT/O=IGI/CN=TRULA GROTHAUS','\0',NULL,NULL,3,151),(152,'2017-03-21 17:50:57','/C=IT/O=IGI/CN=TORY BURDEX','\0',NULL,NULL,3,152),(153,'2017-03-21 17:50:58','/C=IT/O=IGI/CN=NELLIE RUSCHE','\0',NULL,NULL,3,153),(154,'2017-03-21 17:50:58','/C=IT/O=IGI/CN=BRENDA ROMON','\0',NULL,NULL,3,154),(155,'2017-03-21 17:50:58','/C=IT/O=IGI/CN=WARREN ZURAWIK','\0',NULL,NULL,3,155),(156,'2017-03-21 17:50:59','/C=IT/O=IGI/CN=JANYCE HOLJE','\0',NULL,NULL,3,156),(157,'2017-03-21 17:50:59','/C=IT/O=IGI/CN=LELIA BUSHNER','\0',NULL,NULL,3,157),(158,'2017-03-21 17:50:59','/C=IT/O=IGI/CN=CHESTER DESUE','\0',NULL,NULL,3,158),(159,'2017-03-21 17:51:00','/C=IT/O=IGI/CN=MELLISSA MAKINEN','\0',NULL,NULL,3,159),(160,'2017-03-21 17:51:00','/C=IT/O=IGI/CN=ADRIAN DACHS','\0',NULL,NULL,3,160),(161,'2017-03-21 17:51:00','/C=IT/O=IGI/CN=WAN COSIER','\0',NULL,NULL,3,161),(162,'2017-03-21 17:51:01','/C=IT/O=IGI/CN=DORATHY CARDON','\0',NULL,NULL,3,162),(163,'2017-03-21 17:51:01','/C=IT/O=IGI/CN=GLYNDA STARN','\0',NULL,NULL,3,163),(164,'2017-03-21 17:51:02','/C=IT/O=IGI/CN=MITCHELL CRIMIN','\0',NULL,NULL,3,164),(165,'2017-03-21 17:51:02','/C=IT/O=IGI/CN=KATHERIN GIRLING','\0',NULL,NULL,3,165),(166,'2017-03-21 17:51:02','/C=IT/O=IGI/CN=ELISHA MANSER','\0',NULL,NULL,3,166),(167,'2017-03-21 17:51:03','/C=IT/O=IGI/CN=ARVILLA BERTELS','\0',NULL,NULL,3,167),(168,'2017-03-21 17:51:03','/C=IT/O=IGI/CN=HANNAH TAMMO','\0',NULL,NULL,3,168),(169,'2017-03-21 17:51:04','/C=IT/O=IGI/CN=RUDOLF STETZ','\0',NULL,NULL,3,169),(170,'2017-03-21 17:51:04','/C=IT/O=IGI/CN=CATHARINE PAYWA','\0',NULL,NULL,3,170),(171,'2017-03-21 17:51:04','/C=IT/O=IGI/CN=CATALINA VANHOOSER','\0',NULL,NULL,3,171),(172,'2017-03-21 17:51:05','/C=IT/O=IGI/CN=NICOLLE VAUTOUR','\0',NULL,NULL,3,172),(173,'2017-03-21 17:51:05','/C=IT/O=IGI/CN=ROSELIA ERDMANN','\0',NULL,NULL,3,173),(174,'2017-03-21 17:51:05','/C=IT/O=IGI/CN=SLYVIA BEADNELL','\0',NULL,NULL,3,174),(175,'2017-03-21 17:51:06','/C=IT/O=IGI/CN=SOLEDAD RAZER','\0',NULL,NULL,3,175),(176,'2017-03-21 17:51:06','/C=IT/O=IGI/CN=MICHALE VRABEL','\0',NULL,NULL,3,176),(177,'2017-03-21 17:51:06','/C=IT/O=IGI/CN=RAMIRO VANGUILDER','\0',NULL,NULL,3,177),(178,'2017-03-21 17:51:07','/C=IT/O=IGI/CN=ISA GALLEHER','\0',NULL,NULL,3,178),(179,'2017-03-21 17:51:08','/C=IT/O=IGI/CN=CHRISTENA STALLEY','\0',NULL,NULL,3,179),(180,'2017-03-21 17:51:08','/C=IT/O=IGI/CN=MARILU NABARRETE','\0',NULL,NULL,3,180),(181,'2017-03-21 17:51:09','/C=IT/O=IGI/CN=MYRIAM CRONQUIST','\0',NULL,NULL,3,181),(182,'2017-03-21 17:51:09','/C=IT/O=IGI/CN=VICTOR VANSLYKE','\0',NULL,NULL,3,182),(183,'2017-03-21 17:51:10','/C=IT/O=IGI/CN=JACKELINE BRITT','\0',NULL,NULL,3,183),(184,'2017-03-21 17:51:10','/C=IT/O=IGI/CN=KEVIN SWOPE','\0',NULL,NULL,3,184),(185,'2017-03-21 17:51:11','/C=IT/O=IGI/CN=EMERITA SWICEGOOD','\0',NULL,NULL,3,185),(186,'2017-03-21 17:51:11','/C=IT/O=IGI/CN=FANNIE BUGNI','\0',NULL,NULL,3,186),(187,'2017-03-21 17:51:11','/C=IT/O=IGI/CN=TERESA SKRETOWICZ','\0',NULL,NULL,3,187),(188,'2017-03-21 17:51:12','/C=IT/O=IGI/CN=LASANDRA KHN','\0',NULL,NULL,3,188),(189,'2017-03-21 17:51:12','/C=IT/O=IGI/CN=KARIE MCVINNEY','\0',NULL,NULL,3,189),(190,'2017-03-21 17:51:12','/C=IT/O=IGI/CN=CRYSTLE HASSEL','\0',NULL,NULL,3,190),(191,'2017-03-21 17:51:13','/C=IT/O=IGI/CN=WILLIAN GREAM','\0',NULL,NULL,3,191),(192,'2017-03-21 17:51:13','/C=IT/O=IGI/CN=MILDRED WOJTAS','\0',NULL,NULL,3,192),(193,'2017-03-21 17:51:14','/C=IT/O=IGI/CN=ALISON HUBERTY','\0',NULL,NULL,3,193),(194,'2017-03-21 17:51:14','/C=IT/O=IGI/CN=DELFINA MCGARR','\0',NULL,NULL,3,194),(195,'2017-03-21 17:51:15','/C=IT/O=IGI/CN=CUC PIZZO','\0',NULL,NULL,3,195),(196,'2017-03-21 17:51:15','/C=IT/O=IGI/CN=DAKOTA BILLINGSLY','\0',NULL,NULL,3,196),(197,'2017-03-21 17:51:15','/C=IT/O=IGI/CN=NAM GUEVANA','\0',NULL,NULL,3,197),(198,'2017-03-21 17:51:16','/C=IT/O=IGI/CN=HYE HOGGAN','\0',NULL,NULL,3,198),(199,'2017-03-21 17:51:16','/C=IT/O=IGI/CN=ELFRIEDE BUETI','\0',NULL,NULL,3,199),(200,'2017-03-21 17:51:16','/C=IT/O=IGI/CN=HIRAM LAMPMAN','\0',NULL,NULL,3,200); +/*!40000 ALTER TABLE `certificate` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `certificate_request` +-- + +DROP TABLE IF EXISTS `certificate_request`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `certificate_request` ( + `certificate` tinyblob, + `certificateIssuer` varchar(255) NOT NULL, + `certificateSubject` varchar(255) NOT NULL, + `request_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + KEY `FK47CA53E7D75D60A4` (`request_id`), + CONSTRAINT `FK47CA53E7D75D60A4` FOREIGN KEY (`request_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `certificate_request` +-- + +LOCK TABLES `certificate_request` WRITE; +/*!40000 ALTER TABLE `certificate_request` DISABLE KEYS */; +/*!40000 ALTER TABLE `certificate_request` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `group_attrs` +-- + +DROP TABLE IF EXISTS `group_attrs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `group_attrs` ( + `a_id` bigint(20) NOT NULL, + `g_id` bigint(20) NOT NULL, + `a_value` varchar(255) DEFAULT NULL, + PRIMARY KEY (`a_id`,`g_id`), + KEY `FK40B1A2E2DEFC581C` (`g_id`), + KEY `FK40B1A2E2566C2A8F` (`a_id`), + CONSTRAINT `FK40B1A2E2566C2A8F` FOREIGN KEY (`a_id`) REFERENCES `attributes` (`a_id`), + CONSTRAINT `FK40B1A2E2DEFC581C` FOREIGN KEY (`g_id`) REFERENCES `groups` (`gid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `group_attrs` +-- + +LOCK TABLES `group_attrs` WRITE; +/*!40000 ALTER TABLE `group_attrs` DISABLE KEYS */; +INSERT INTO `group_attrs` VALUES (3,2,'g_1'),(3,3,'g_2'),(3,4,'g_3'),(3,5,'g_4'),(3,6,'g_5'),(3,7,'g_6'),(3,8,'g_7'),(3,9,'g_8'),(3,10,'g_9'),(3,11,'g_10'); +/*!40000 ALTER TABLE `group_attrs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `group_membership_req` +-- + +DROP TABLE IF EXISTS `group_membership_req`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `group_membership_req` ( + `groupName` varchar(255) NOT NULL, + `request_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + KEY `FKBD145E75D75D60A4` (`request_id`), + CONSTRAINT `FKBD145E75D75D60A4` FOREIGN KEY (`request_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `group_membership_req` +-- + +LOCK TABLES `group_membership_req` WRITE; +/*!40000 ALTER TABLE `group_membership_req` DISABLE KEYS */; +/*!40000 ALTER TABLE `group_membership_req` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `groups` +-- + +DROP TABLE IF EXISTS `groups`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `groups` ( + `gid` bigint(20) NOT NULL AUTO_INCREMENT, + `dn` varchar(255) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `parent` bigint(20) DEFAULT NULL, + `must` bit(1) NOT NULL, + `restricted` bit(1) DEFAULT NULL, + PRIMARY KEY (`gid`), + UNIQUE KEY `dn` (`dn`), + KEY `FKB63DD9D4A3771CD3` (`parent`), + CONSTRAINT `FKB63DD9D4A3771CD3` FOREIGN KEY (`parent`) REFERENCES `groups` (`gid`) +) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `groups` +-- + +LOCK TABLES `groups` WRITE; +/*!40000 ALTER TABLE `groups` DISABLE KEYS */; +INSERT INTO `groups` VALUES (1,'/test_0',NULL,1,'',NULL),(2,'/test_0/g_1',NULL,1,'',NULL),(3,'/test_0/g_2',NULL,1,'',NULL),(4,'/test_0/g_3',NULL,1,'',NULL),(5,'/test_0/g_4',NULL,1,'',NULL),(6,'/test_0/g_5',NULL,1,'',NULL),(7,'/test_0/g_6',NULL,1,'',NULL),(8,'/test_0/g_7',NULL,1,'',NULL),(9,'/test_0/g_8',NULL,1,'',NULL),(10,'/test_0/g_9',NULL,1,'',NULL),(11,'/test_0/g_10',NULL,1,'',NULL),(12,'/test_0/g_11',NULL,1,'',NULL),(13,'/test_0/g_12',NULL,1,'',NULL),(14,'/test_0/g_13',NULL,1,'',NULL),(15,'/test_0/g_14',NULL,1,'',NULL),(16,'/test_0/g_15',NULL,1,'',NULL),(17,'/test_0/g_16',NULL,1,'',NULL),(18,'/test_0/g_17',NULL,1,'',NULL),(19,'/test_0/g_18',NULL,1,'',NULL),(20,'/test_0/g_19',NULL,1,'',NULL),(21,'/test_0/g_20',NULL,1,'',NULL),(22,'/test_0/g_21',NULL,1,'',NULL),(23,'/test_0/g_22',NULL,1,'',NULL),(24,'/test_0/g_23',NULL,1,'',NULL),(25,'/test_0/g_24',NULL,1,'',NULL),(26,'/test_0/g_25',NULL,1,'',NULL),(27,'/test_0/g_26',NULL,1,'',NULL),(28,'/test_0/g_27',NULL,1,'',NULL),(29,'/test_0/g_28',NULL,1,'',NULL),(30,'/test_0/g_29',NULL,1,'',NULL),(31,'/test_0/g_30',NULL,1,'',NULL),(32,'/test_0/g_31',NULL,1,'',NULL),(33,'/test_0/g_32',NULL,1,'',NULL),(34,'/test_0/g_33',NULL,1,'',NULL),(35,'/test_0/g_34',NULL,1,'',NULL),(36,'/test_0/g_35',NULL,1,'',NULL),(37,'/test_0/g_36',NULL,1,'',NULL),(38,'/test_0/g_37',NULL,1,'',NULL),(39,'/test_0/g_38',NULL,1,'',NULL),(40,'/test_0/g_39',NULL,1,'',NULL); +/*!40000 ALTER TABLE `groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `m` +-- + +DROP TABLE IF EXISTS `m`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `m` ( + `mapping_id` bigint(20) NOT NULL AUTO_INCREMENT, + `gid` bigint(20) NOT NULL, + `rid` bigint(20) DEFAULT NULL, + `userid` bigint(20) NOT NULL, + PRIMARY KEY (`mapping_id`), + UNIQUE KEY `gid` (`gid`,`rid`,`userid`), + KEY `fk_m_groups` (`gid`), + KEY `fk_m_roles` (`rid`), + KEY `fk_m_usr` (`userid`), + CONSTRAINT `fk_m_groups` FOREIGN KEY (`gid`) REFERENCES `groups` (`gid`) ON DELETE CASCADE, + CONSTRAINT `fk_m_roles` FOREIGN KEY (`rid`) REFERENCES `roles` (`rid`) ON DELETE CASCADE, + CONSTRAINT `fk_m_usr` FOREIGN KEY (`userid`) REFERENCES `usr` (`userid`) +) ENGINE=InnoDB AUTO_INCREMENT=313 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `m` +-- + +LOCK TABLES `m` WRITE; +/*!40000 ALTER TABLE `m` DISABLE KEYS */; +INSERT INTO `m` VALUES (1,1,NULL,1),(2,1,NULL,2),(3,1,NULL,3),(4,1,NULL,4),(5,1,NULL,5),(6,1,NULL,6),(7,1,NULL,7),(8,1,NULL,8),(9,1,NULL,9),(10,1,NULL,10),(11,1,NULL,11),(12,1,NULL,12),(13,1,NULL,13),(14,1,NULL,14),(15,1,NULL,15),(16,1,NULL,16),(17,1,NULL,17),(18,1,NULL,18),(19,1,NULL,19),(20,1,NULL,20),(21,1,NULL,21),(22,1,NULL,22),(23,1,NULL,23),(24,1,NULL,24),(25,1,NULL,25),(26,1,NULL,26),(27,1,NULL,27),(28,1,NULL,28),(29,1,NULL,29),(30,1,NULL,30),(31,1,NULL,31),(32,1,NULL,32),(33,1,NULL,33),(34,1,NULL,34),(35,1,NULL,35),(36,1,NULL,36),(37,1,NULL,37),(38,1,NULL,38),(39,1,NULL,39),(40,1,NULL,40),(41,1,NULL,41),(42,1,NULL,42),(43,1,NULL,43),(44,1,NULL,44),(45,1,NULL,45),(46,1,NULL,46),(47,1,NULL,47),(48,1,NULL,48),(49,1,NULL,49),(50,1,NULL,50),(51,1,NULL,51),(52,1,NULL,52),(53,1,NULL,53),(54,1,NULL,54),(55,1,NULL,55),(56,1,NULL,56),(57,1,NULL,57),(58,1,NULL,58),(59,1,NULL,59),(60,1,NULL,60),(61,1,NULL,61),(62,1,NULL,62),(63,1,NULL,63),(64,1,NULL,64),(65,1,NULL,65),(66,1,NULL,66),(67,1,NULL,67),(68,1,NULL,68),(69,1,NULL,69),(70,1,NULL,70),(71,1,NULL,71),(72,1,NULL,72),(73,1,NULL,73),(74,1,NULL,74),(75,1,NULL,75),(76,1,NULL,76),(77,1,NULL,77),(78,1,NULL,78),(79,1,NULL,79),(80,1,NULL,80),(81,1,NULL,81),(82,1,NULL,82),(83,1,NULL,83),(84,1,NULL,84),(85,1,NULL,85),(86,1,NULL,86),(87,1,NULL,87),(88,1,NULL,88),(89,1,NULL,89),(90,1,NULL,90),(91,1,NULL,91),(92,1,NULL,92),(93,1,NULL,93),(94,1,NULL,94),(95,1,NULL,95),(96,1,NULL,96),(97,1,NULL,97),(98,1,NULL,98),(99,1,NULL,99),(100,1,NULL,100),(101,1,NULL,101),(102,1,NULL,102),(103,1,NULL,103),(104,1,NULL,104),(105,1,NULL,105),(106,1,NULL,106),(107,1,NULL,107),(108,1,NULL,108),(109,1,NULL,109),(110,1,NULL,110),(111,1,NULL,111),(112,1,NULL,112),(113,1,NULL,113),(114,1,NULL,114),(115,1,NULL,115),(116,1,NULL,116),(117,1,NULL,117),(118,1,NULL,118),(119,1,NULL,119),(120,1,NULL,120),(121,1,NULL,121),(122,1,NULL,122),(123,1,NULL,123),(124,1,NULL,124),(125,1,NULL,125),(126,1,NULL,126),(127,1,NULL,127),(128,1,NULL,128),(129,1,NULL,129),(130,1,NULL,130),(131,1,NULL,131),(132,1,NULL,132),(133,1,NULL,133),(134,1,NULL,134),(135,1,NULL,135),(136,1,NULL,136),(137,1,NULL,137),(138,1,NULL,138),(139,1,NULL,139),(140,1,NULL,140),(141,1,NULL,141),(142,1,NULL,142),(143,1,NULL,143),(144,1,NULL,144),(145,1,NULL,145),(146,1,NULL,146),(147,1,NULL,147),(148,1,NULL,148),(149,1,NULL,149),(150,1,NULL,150),(151,1,NULL,151),(152,1,NULL,152),(153,1,NULL,153),(154,1,NULL,154),(155,1,NULL,155),(156,1,NULL,156),(157,1,NULL,157),(158,1,NULL,158),(159,1,NULL,159),(160,1,NULL,160),(161,1,NULL,161),(162,1,NULL,162),(163,1,NULL,163),(164,1,NULL,164),(165,1,NULL,165),(166,1,NULL,166),(167,1,NULL,167),(168,1,NULL,168),(169,1,NULL,169),(170,1,NULL,170),(171,1,NULL,171),(172,1,NULL,172),(173,1,NULL,173),(174,1,NULL,174),(175,1,NULL,175),(176,1,NULL,176),(177,1,NULL,177),(178,1,NULL,178),(179,1,NULL,179),(180,1,NULL,180),(181,1,NULL,181),(182,1,NULL,182),(183,1,NULL,183),(184,1,NULL,184),(185,1,NULL,185),(186,1,NULL,186),(187,1,NULL,187),(188,1,NULL,188),(189,1,NULL,189),(190,1,NULL,190),(191,1,NULL,191),(192,1,NULL,192),(193,1,NULL,193),(194,1,NULL,194),(195,1,NULL,195),(196,1,NULL,196),(197,1,NULL,197),(198,1,NULL,198),(199,1,NULL,199),(200,1,NULL,200),(302,1,1,100),(303,1,1,101),(304,1,1,102),(305,1,1,103),(306,1,1,104),(307,1,1,105),(308,1,1,106),(309,1,1,107),(310,1,1,108),(311,1,1,109),(312,1,1,110),(201,2,NULL,1),(202,2,NULL,2),(203,2,NULL,3),(204,2,NULL,4),(205,2,NULL,5),(206,2,NULL,6),(207,2,NULL,7),(208,2,NULL,8),(209,2,NULL,9),(210,2,NULL,10),(211,2,NULL,11),(212,2,NULL,12),(213,2,NULL,13),(214,2,NULL,14),(215,2,NULL,15),(216,2,NULL,16),(217,2,NULL,17),(218,2,NULL,18),(219,2,NULL,19),(220,2,NULL,20),(221,2,NULL,21),(222,2,NULL,22),(223,2,NULL,23),(224,2,NULL,24),(225,2,NULL,25),(226,2,NULL,26),(227,2,NULL,27),(228,2,NULL,28),(229,2,NULL,29),(230,2,NULL,30),(231,3,NULL,30),(232,3,NULL,31),(233,3,NULL,32),(234,3,NULL,33),(235,3,NULL,34),(236,3,NULL,35),(237,3,NULL,36),(238,3,NULL,37),(239,3,NULL,38),(240,3,NULL,39),(241,3,NULL,40),(242,3,NULL,41),(243,3,NULL,42),(244,3,NULL,43),(245,3,NULL,44),(246,3,NULL,45),(247,3,NULL,46),(248,3,NULL,47),(249,3,NULL,48),(250,3,NULL,49),(251,3,NULL,50),(252,3,NULL,51),(253,3,NULL,52),(254,3,NULL,53),(255,3,NULL,54),(256,3,NULL,55),(257,3,NULL,56),(258,3,NULL,57),(259,3,NULL,58),(260,3,NULL,59),(261,3,NULL,60),(262,3,NULL,61),(263,3,NULL,62),(264,3,NULL,63),(265,3,NULL,64),(266,3,NULL,65),(267,3,NULL,66),(268,3,NULL,67),(269,3,NULL,68),(270,3,NULL,69),(271,3,NULL,70),(272,3,NULL,71),(273,3,NULL,72),(274,3,NULL,73),(275,3,NULL,74),(276,3,NULL,75),(277,3,NULL,76),(278,3,NULL,77),(279,3,NULL,78),(280,3,NULL,79),(281,3,NULL,80),(282,3,NULL,81),(283,3,NULL,82),(284,3,NULL,83),(285,3,NULL,84),(286,3,NULL,85),(287,3,NULL,86),(288,3,NULL,87),(289,3,NULL,88),(290,3,NULL,89),(291,3,NULL,90),(292,3,NULL,91),(293,3,NULL,92),(294,3,NULL,93),(295,3,NULL,94),(296,3,NULL,95),(297,3,NULL,96),(298,3,NULL,97),(299,3,NULL,98),(300,3,NULL,99),(301,3,NULL,100); +/*!40000 ALTER TABLE `m` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `managers` +-- + +DROP TABLE IF EXISTS `managers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `managers` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `description` varchar(255) NOT NULL, + `email_address` varchar(255) NOT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `managers` +-- + +LOCK TABLES `managers` WRITE; +/*!40000 ALTER TABLE `managers` DISABLE KEYS */; +/*!40000 ALTER TABLE `managers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `managers_groups` +-- + +DROP TABLE IF EXISTS `managers_groups`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `managers_groups` ( + `manager_id` bigint(20) NOT NULL, + `group_id` bigint(20) NOT NULL, + PRIMARY KEY (`manager_id`,`group_id`), + KEY `FK8F5E11CDFCFA8B04` (`group_id`), + KEY `FK8F5E11CDABC81A12` (`manager_id`), + CONSTRAINT `FK8F5E11CDABC81A12` FOREIGN KEY (`manager_id`) REFERENCES `managers` (`id`), + CONSTRAINT `FK8F5E11CDFCFA8B04` FOREIGN KEY (`group_id`) REFERENCES `groups` (`gid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `managers_groups` +-- + +LOCK TABLES `managers_groups` WRITE; +/*!40000 ALTER TABLE `managers_groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `managers_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `membership_rem_req` +-- + +DROP TABLE IF EXISTS `membership_rem_req`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `membership_rem_req` ( + `reason` varchar(255) NOT NULL, + `request_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + KEY `FK1877BC10D75D60A4` (`request_id`), + CONSTRAINT `FK1877BC10D75D60A4` FOREIGN KEY (`request_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `membership_rem_req` +-- + +LOCK TABLES `membership_rem_req` WRITE; +/*!40000 ALTER TABLE `membership_rem_req` DISABLE KEYS */; +/*!40000 ALTER TABLE `membership_rem_req` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `periodic_notifications` +-- + +DROP TABLE IF EXISTS `periodic_notifications`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `periodic_notifications` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `lastNotificationTime` datetime NOT NULL, + `notificationType` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `notificationType` (`notificationType`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `periodic_notifications` +-- + +LOCK TABLES `periodic_notifications` WRITE; +/*!40000 ALTER TABLE `periodic_notifications` DISABLE KEYS */; +/*!40000 ALTER TABLE `periodic_notifications` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `personal_info` +-- + +DROP TABLE IF EXISTS `personal_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `personal_info` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `value` varchar(255) DEFAULT NULL, + `visible` bit(1) DEFAULT NULL, + `personal_info_type_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + KEY `FK229FDF4DA8D3C6BC` (`personal_info_type_id`), + CONSTRAINT `FK229FDF4DA8D3C6BC` FOREIGN KEY (`personal_info_type_id`) REFERENCES `personal_info_type` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `personal_info` +-- + +LOCK TABLES `personal_info` WRITE; +/*!40000 ALTER TABLE `personal_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `personal_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `personal_info_type` +-- + +DROP TABLE IF EXISTS `personal_info_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `personal_info_type` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `description` varchar(255) DEFAULT NULL, + `type` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `type` (`type`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `personal_info_type` +-- + +LOCK TABLES `personal_info_type` WRITE; +/*!40000 ALTER TABLE `personal_info_type` DISABLE KEYS */; +/*!40000 ALTER TABLE `personal_info_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `req` +-- + +DROP TABLE IF EXISTS `req`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `req` ( + `request_id` bigint(20) NOT NULL AUTO_INCREMENT, + `approver_ca` varchar(255) DEFAULT NULL, + `approver_dn` varchar(255) DEFAULT NULL, + `completionDate` datetime DEFAULT NULL, + `creationDate` datetime DEFAULT NULL, + `expirationDate` datetime DEFAULT NULL, + `status` varchar(255) NOT NULL, + `requester_info_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + UNIQUE KEY `requester_info_id` (`requester_info_id`), + KEY `FK1B89EC37E889D` (`requester_info_id`), + CONSTRAINT `FK1B89EC37E889D` FOREIGN KEY (`requester_info_id`) REFERENCES `requester_info` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `req` +-- + +LOCK TABLES `req` WRITE; +/*!40000 ALTER TABLE `req` DISABLE KEYS */; +/*!40000 ALTER TABLE `req` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `requester_info` +-- + +DROP TABLE IF EXISTS `requester_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `requester_info` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `address` varchar(255) DEFAULT NULL, + `certificateIssuer` varchar(255) NOT NULL, + `certificateSubject` varchar(255) NOT NULL, + `emailAddress` varchar(255) NOT NULL, + `institution` varchar(255) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `phoneNumber` varchar(255) DEFAULT NULL, + `surname` varchar(255) DEFAULT NULL, + `voMember` bit(1) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `requester_info` +-- + +LOCK TABLES `requester_info` WRITE; +/*!40000 ALTER TABLE `requester_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `requester_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `requester_personal_info` +-- + +DROP TABLE IF EXISTS `requester_personal_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `requester_personal_info` ( + `requester_id` bigint(20) NOT NULL, + `pi_value` varchar(255) DEFAULT NULL, + `pi_key` varchar(255) NOT NULL, + PRIMARY KEY (`requester_id`,`pi_key`), + KEY `FK7E3D7FCAD500B8D2` (`requester_id`), + CONSTRAINT `FK7E3D7FCAD500B8D2` FOREIGN KEY (`requester_id`) REFERENCES `requester_info` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `requester_personal_info` +-- + +LOCK TABLES `requester_personal_info` WRITE; +/*!40000 ALTER TABLE `requester_personal_info` DISABLE KEYS */; +/*!40000 ALTER TABLE `requester_personal_info` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_attrs` +-- + +DROP TABLE IF EXISTS `role_attrs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_attrs` ( + `a_id` bigint(20) NOT NULL, + `g_id` bigint(20) NOT NULL, + `r_id` bigint(20) NOT NULL, + `a_value` varchar(255) DEFAULT NULL, + PRIMARY KEY (`a_id`,`g_id`,`r_id`), + KEY `FK6BDE9799DEFC581C` (`g_id`), + KEY `FK6BDE9799566C2A8F` (`a_id`), + KEY `FK6BDE979920304994` (`r_id`), + CONSTRAINT `FK6BDE979920304994` FOREIGN KEY (`r_id`) REFERENCES `roles` (`rid`) ON DELETE CASCADE, + CONSTRAINT `FK6BDE9799566C2A8F` FOREIGN KEY (`a_id`) REFERENCES `attributes` (`a_id`), + CONSTRAINT `FK6BDE9799DEFC581C` FOREIGN KEY (`g_id`) REFERENCES `groups` (`gid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_attrs` +-- + +LOCK TABLES `role_attrs` WRITE; +/*!40000 ALTER TABLE `role_attrs` DISABLE KEYS */; +INSERT INTO `role_attrs` VALUES (2,2,1,'g_1 in VO-Admin'),(2,3,1,'g_2 in VO-Admin'),(2,4,1,'g_3 in VO-Admin'),(2,5,1,'g_4 in VO-Admin'),(2,6,1,'g_5 in VO-Admin'),(2,7,1,'g_6 in VO-Admin'),(2,8,1,'g_7 in VO-Admin'),(2,9,1,'g_8 in VO-Admin'),(2,10,1,'g_9 in VO-Admin'),(2,11,1,'g_10 in VO-Admin'); +/*!40000 ALTER TABLE `role_attrs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_membership_req` +-- + +DROP TABLE IF EXISTS `role_membership_req`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_membership_req` ( + `groupName` varchar(255) DEFAULT NULL, + `roleName` varchar(255) DEFAULT NULL, + `request_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + KEY `FK3B9C79ED75D60A4` (`request_id`), + CONSTRAINT `FK3B9C79ED75D60A4` FOREIGN KEY (`request_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_membership_req` +-- + +LOCK TABLES `role_membership_req` WRITE; +/*!40000 ALTER TABLE `role_membership_req` DISABLE KEYS */; +/*!40000 ALTER TABLE `role_membership_req` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles` +-- + +DROP TABLE IF EXISTS `roles`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles` ( + `rid` bigint(20) NOT NULL AUTO_INCREMENT, + `role` varchar(255) NOT NULL, + PRIMARY KEY (`rid`), + UNIQUE KEY `role` (`role`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles` +-- + +LOCK TABLES `roles` WRITE; +/*!40000 ALTER TABLE `roles` DISABLE KEYS */; +INSERT INTO `roles` VALUES (2,'r_1'),(3,'r_2'),(4,'r_3'),(5,'r_4'),(6,'r_5'),(7,'r_6'),(8,'r_7'),(9,'r_8'),(10,'r_9'),(1,'VO-Admin'); +/*!40000 ALTER TABLE `roles` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `sign_aup_task` +-- + +DROP TABLE IF EXISTS `sign_aup_task`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sign_aup_task` ( + `task_id` bigint(20) NOT NULL, + `aup_id` bigint(20) NOT NULL, + PRIMARY KEY (`task_id`), + KEY `FK7FCB416ADA1C6363` (`aup_id`), + KEY `FK7FCB416A32B8C70C` (`task_id`), + CONSTRAINT `FK7FCB416A32B8C70C` FOREIGN KEY (`task_id`) REFERENCES `task` (`task_id`), + CONSTRAINT `FK7FCB416ADA1C6363` FOREIGN KEY (`aup_id`) REFERENCES `aup` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sign_aup_task` +-- + +LOCK TABLES `sign_aup_task` WRITE; +/*!40000 ALTER TABLE `sign_aup_task` DISABLE KEYS */; +/*!40000 ALTER TABLE `sign_aup_task` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `task` +-- + +DROP TABLE IF EXISTS `task`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `task` ( + `task_id` bigint(20) NOT NULL AUTO_INCREMENT, + `completionDate` datetime DEFAULT NULL, + `creationDate` datetime DEFAULT NULL, + `expiryDate` datetime DEFAULT NULL, + `status` varchar(255) NOT NULL, + `admin_id` bigint(20) DEFAULT NULL, + `task_type_id` bigint(20) NOT NULL, + `usr_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`task_id`), + KEY `FK3635859AD54C57` (`task_type_id`), + KEY `FK363585EE2D4487` (`usr_id`), + KEY `FK363585A4AD9904` (`admin_id`), + CONSTRAINT `FK3635859AD54C57` FOREIGN KEY (`task_type_id`) REFERENCES `task_type` (`id`), + CONSTRAINT `FK363585A4AD9904` FOREIGN KEY (`admin_id`) REFERENCES `admins` (`adminid`), + CONSTRAINT `FK363585EE2D4487` FOREIGN KEY (`usr_id`) REFERENCES `usr` (`userid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `task` +-- + +LOCK TABLES `task` WRITE; +/*!40000 ALTER TABLE `task` DISABLE KEYS */; +/*!40000 ALTER TABLE `task` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `task_log_record` +-- + +DROP TABLE IF EXISTS `task_log_record`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `task_log_record` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `adminDn` varchar(255) DEFAULT NULL, + `creation_time` datetime NOT NULL, + `event` varchar(255) NOT NULL, + `userDn` varchar(255) DEFAULT NULL, + `task_id` bigint(20) NOT NULL, + PRIMARY KEY (`id`), + KEY `FK77673CA632B8C70C` (`task_id`), + CONSTRAINT `FK77673CA632B8C70C` FOREIGN KEY (`task_id`) REFERENCES `task` (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `task_log_record` +-- + +LOCK TABLES `task_log_record` WRITE; +/*!40000 ALTER TABLE `task_log_record` DISABLE KEYS */; +/*!40000 ALTER TABLE `task_log_record` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `task_type` +-- + +DROP TABLE IF EXISTS `task_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `task_type` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `description` varchar(255) DEFAULT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `task_type` +-- + +LOCK TABLES `task_type` WRITE; +/*!40000 ALTER TABLE `task_type` DISABLE KEYS */; +INSERT INTO `task_type` VALUES (1,'Tasks of this type are assigned to users that need to sign, or resign an AUP.','SignAUPTask'),(2,'Tasks of this type are assigned to VO admins that need to approve users\' requests.','ApproveUserRequestTask'); +/*!40000 ALTER TABLE `task_type` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_request_task` +-- + +DROP TABLE IF EXISTS `user_request_task`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_request_task` ( + `task_id` bigint(20) NOT NULL, + `req_id` bigint(20) NOT NULL, + PRIMARY KEY (`task_id`), + KEY `FKACB7D299D73AC35` (`req_id`), + KEY `FKACB7D2932B8C70C` (`task_id`), + CONSTRAINT `FKACB7D2932B8C70C` FOREIGN KEY (`task_id`) REFERENCES `task` (`task_id`), + CONSTRAINT `FKACB7D299D73AC35` FOREIGN KEY (`req_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_request_task` +-- + +LOCK TABLES `user_request_task` WRITE; +/*!40000 ALTER TABLE `user_request_task` DISABLE KEYS */; +/*!40000 ALTER TABLE `user_request_task` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `usr` +-- + +DROP TABLE IF EXISTS `usr`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `usr` ( + `userid` bigint(20) NOT NULL AUTO_INCREMENT, + `address` varchar(255) DEFAULT NULL, + `creation_time` datetime NOT NULL, + `dn` varchar(255) DEFAULT NULL, + `email_address` varchar(255) NOT NULL, + `end_time` datetime NOT NULL, + `institution` varchar(255) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `phone_number` varchar(255) DEFAULT NULL, + `surname` varchar(255) DEFAULT NULL, + `suspended` bit(1) DEFAULT NULL, + `suspension_reason` varchar(255) DEFAULT NULL, + `suspension_reason_code` varchar(255) DEFAULT NULL, + `ca` smallint(6) DEFAULT NULL, + PRIMARY KEY (`userid`), + KEY `FK1C5947C6FEB32` (`ca`), + CONSTRAINT `FK1C5947C6FEB32` FOREIGN KEY (`ca`) REFERENCES `ca` (`cid`) +) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `usr` +-- + +LOCK TABLES `usr` WRITE; +/*!40000 ALTER TABLE `usr` DISABLE KEYS */; +INSERT INTO `usr` VALUES (1,'(some address)','2017-03-21 17:49:50','/C=IT/O=IGI/CN=CONRAD BASSETTE','CONRAD.BASSETTE.1@voms.test.io','2018-03-21 17:49:50','CNAF - Italian National Center for Research and Development (CNAF)','CONRAD',NULL,'BASSETTE','\0',NULL,NULL,NULL),(2,'(some address)','2017-03-21 17:49:50','/C=IT/O=IGI/CN=MICHAELA MCPHERREN','MICHAELA.MCPHERREN.2@voms.test.io','2018-03-21 17:49:50','CNAF - Italian National Center for Research and Development (CNAF)','MICHAELA',NULL,'MCPHERREN','\0',NULL,NULL,NULL),(3,'(some address)','2017-03-21 17:49:51','/C=IT/O=IGI/CN=TINY KABLER','TINY.KABLER.3@voms.test.io','2018-03-21 17:49:51','CNAF - Italian National Center for Research and Development (CNAF)','TINY',NULL,'KABLER','\0',NULL,NULL,NULL),(4,'(some address)','2017-03-21 17:49:52','/C=IT/O=IGI/CN=HAI JACOBOVITS','HAI.JACOBOVITS.4@voms.test.io','2018-03-21 17:49:52','CNAF - Italian National Center for Research and Development (CNAF)','HAI',NULL,'JACOBOVITS','\0',NULL,NULL,NULL),(5,'(some address)','2017-03-21 17:49:52','/C=IT/O=IGI/CN=MCKENZIE DELANG','MCKENZIE.DELANG.5@voms.test.io','2018-03-21 17:49:52','CNAF - Italian National Center for Research and Development (CNAF)','MCKENZIE',NULL,'DELANG','\0',NULL,NULL,NULL),(6,'(some address)','2017-03-21 17:49:53','/C=IT/O=IGI/CN=CECILY ANDERTON','CECILY.ANDERTON.6@voms.test.io','2018-03-21 17:49:53','CNAF - Italian National Center for Research and Development (CNAF)','CECILY',NULL,'ANDERTON','\0',NULL,NULL,NULL),(7,'(some address)','2017-03-21 17:49:53','/C=IT/O=IGI/CN=LATESHA SPINOZA','LATESHA.SPINOZA.7@voms.test.io','2018-03-21 17:49:53','CNAF - Italian National Center for Research and Development (CNAF)','LATESHA',NULL,'SPINOZA','\0',NULL,NULL,NULL),(8,'(some address)','2017-03-21 17:49:54','/C=IT/O=IGI/CN=SHAQUANA KONON','SHAQUANA.KONON.8@voms.test.io','2018-03-21 17:49:54','CNAF - Italian National Center for Research and Development (CNAF)','SHAQUANA',NULL,'KONON','\0',NULL,NULL,NULL),(9,'(some address)','2017-03-21 17:49:55','/C=IT/O=IGI/CN=DANNIE WALSH','DANNIE.WALSH.9@voms.test.io','2018-03-21 17:49:55','CNAF - Italian National Center for Research and Development (CNAF)','DANNIE',NULL,'WALSH','\0',NULL,NULL,NULL),(10,'(some address)','2017-03-21 17:49:55','/C=IT/O=IGI/CN=EUNICE ORLEANS','EUNICE.ORLEANS.10@voms.test.io','2018-03-21 17:49:55','CNAF - Italian National Center for Research and Development (CNAF)','EUNICE',NULL,'ORLEANS','\0',NULL,NULL,NULL),(11,'(some address)','2017-03-21 17:49:55','/C=IT/O=IGI/CN=LAHOMA PRESTINO','LAHOMA.PRESTINO.11@voms.test.io','2018-03-21 17:49:55','CNAF - Italian National Center for Research and Development (CNAF)','LAHOMA',NULL,'PRESTINO','\0',NULL,NULL,NULL),(12,'(some address)','2017-03-21 17:49:56','/C=IT/O=IGI/CN=DOREEN BOURDEAU','DOREEN.BOURDEAU.12@voms.test.io','2018-03-21 17:49:56','CNAF - Italian National Center for Research and Development (CNAF)','DOREEN',NULL,'BOURDEAU','\0',NULL,NULL,NULL),(13,'(some address)','2017-03-21 17:49:56','/C=IT/O=IGI/CN=WAI PINKERTON','WAI.PINKERTON.13@voms.test.io','2018-03-21 17:49:56','CNAF - Italian National Center for Research and Development (CNAF)','WAI',NULL,'PINKERTON','\0',NULL,NULL,NULL),(14,'(some address)','2017-03-21 17:49:57','/C=IT/O=IGI/CN=KACY COLLICA','KACY.COLLICA.14@voms.test.io','2018-03-21 17:49:57','CNAF - Italian National Center for Research and Development (CNAF)','KACY',NULL,'COLLICA','\0',NULL,NULL,NULL),(15,'(some address)','2017-03-21 17:49:57','/C=IT/O=IGI/CN=ADINA PIERETTI','ADINA.PIERETTI.15@voms.test.io','2018-03-21 17:49:57','CNAF - Italian National Center for Research and Development (CNAF)','ADINA',NULL,'PIERETTI','\0',NULL,NULL,NULL),(16,'(some address)','2017-03-21 17:49:57','/C=IT/O=IGI/CN=ANTHONY ELNICKI','ANTHONY.ELNICKI.16@voms.test.io','2018-03-21 17:49:57','CNAF - Italian National Center for Research and Development (CNAF)','ANTHONY',NULL,'ELNICKI','\0',NULL,NULL,NULL),(17,'(some address)','2017-03-21 17:49:58','/C=IT/O=IGI/CN=ERIC RADWAN','ERIC.RADWAN.17@voms.test.io','2018-03-21 17:49:58','CNAF - Italian National Center for Research and Development (CNAF)','ERIC',NULL,'RADWAN','\0',NULL,NULL,NULL),(18,'(some address)','2017-03-21 17:49:58','/C=IT/O=IGI/CN=MARX DALMATA','MARX.DALMATA.18@voms.test.io','2018-03-21 17:49:58','CNAF - Italian National Center for Research and Development (CNAF)','MARX',NULL,'DALMATA','\0',NULL,NULL,NULL),(19,'(some address)','2017-03-21 17:49:59','/C=IT/O=IGI/CN=MADALINE SHERROD','MADALINE.SHERROD.19@voms.test.io','2018-03-21 17:49:59','CNAF - Italian National Center for Research and Development (CNAF)','MADALINE',NULL,'SHERROD','\0',NULL,NULL,NULL),(20,'(some address)','2017-03-21 17:49:59','/C=IT/O=IGI/CN=ABEL BURBACK','ABEL.BURBACK.20@voms.test.io','2018-03-21 17:49:59','CNAF - Italian National Center for Research and Development (CNAF)','ABEL',NULL,'BURBACK','\0',NULL,NULL,NULL),(21,'(some address)','2017-03-21 17:50:00','/C=IT/O=IGI/CN=CALLIE NAGINDAS','CALLIE.NAGINDAS.21@voms.test.io','2018-03-21 17:50:00','CNAF - Italian National Center for Research and Development (CNAF)','CALLIE',NULL,'NAGINDAS','\0',NULL,NULL,NULL),(22,'(some address)','2017-03-21 17:50:00','/C=IT/O=IGI/CN=ABE LERWILL','ABE.LERWILL.22@voms.test.io','2018-03-21 17:50:00','CNAF - Italian National Center for Research and Development (CNAF)','ABE',NULL,'LERWILL','\0',NULL,NULL,NULL),(23,'(some address)','2017-03-21 17:50:01','/C=IT/O=IGI/CN=LOUIS WHITELIGHTNIN','LOUIS.WHITELIGHTNIN.23@voms.test.io','2018-03-21 17:50:01','CNAF - Italian National Center for Research and Development (CNAF)','LOUIS',NULL,'WHITELIGHTNIN','\0',NULL,NULL,NULL),(24,'(some address)','2017-03-21 17:50:01','/C=IT/O=IGI/CN=SHAWNNA LANGLINAIS','SHAWNNA.LANGLINAIS.24@voms.test.io','2018-03-21 17:50:01','CNAF - Italian National Center for Research and Development (CNAF)','SHAWNNA',NULL,'LANGLINAIS','\0',NULL,NULL,NULL),(25,'(some address)','2017-03-21 17:50:02','/C=IT/O=IGI/CN=CHAD CAVALIERO','CHAD.CAVALIERO.25@voms.test.io','2018-03-21 17:50:02','CNAF - Italian National Center for Research and Development (CNAF)','CHAD',NULL,'CAVALIERO','\0',NULL,NULL,NULL),(26,'(some address)','2017-03-21 17:50:02','/C=IT/O=IGI/CN=LAKEISHA MCMORRIS','LAKEISHA.MCMORRIS.26@voms.test.io','2018-03-21 17:50:02','CNAF - Italian National Center for Research and Development (CNAF)','LAKEISHA',NULL,'MCMORRIS','\0',NULL,NULL,NULL),(27,'(some address)','2017-03-21 17:50:03','/C=IT/O=IGI/CN=RODNEY HACHER','RODNEY.HACHER.27@voms.test.io','2018-03-21 17:50:03','CNAF - Italian National Center for Research and Development (CNAF)','RODNEY',NULL,'HACHER','\0',NULL,NULL,NULL),(28,'(some address)','2017-03-21 17:50:03','/C=IT/O=IGI/CN=CARLA DAEHN','CARLA.DAEHN.28@voms.test.io','2018-03-21 17:50:03','CNAF - Italian National Center for Research and Development (CNAF)','CARLA',NULL,'DAEHN','\0',NULL,NULL,NULL),(29,'(some address)','2017-03-21 17:50:04','/C=IT/O=IGI/CN=MARLON KRUPPENBACHER','MARLON.KRUPPENBACHER.29@voms.test.io','2018-03-21 17:50:04','CNAF - Italian National Center for Research and Development (CNAF)','MARLON',NULL,'KRUPPENBACHER','\0',NULL,NULL,NULL),(30,'(some address)','2017-03-21 17:50:04','/C=IT/O=IGI/CN=VERTIE STAMER','VERTIE.STAMER.30@voms.test.io','2018-03-21 17:50:04','CNAF - Italian National Center for Research and Development (CNAF)','VERTIE',NULL,'STAMER','\0',NULL,NULL,NULL),(31,'(some address)','2017-03-21 17:50:04','/C=IT/O=IGI/CN=DELLA BARKLOW','DELLA.BARKLOW.31@voms.test.io','2018-03-21 17:50:04','CNAF - Italian National Center for Research and Development (CNAF)','DELLA',NULL,'BARKLOW','\0',NULL,NULL,NULL),(32,'(some address)','2017-03-21 17:50:05','/C=IT/O=IGI/CN=CECILIA LALL','CECILIA.LALL.32@voms.test.io','2018-03-21 17:50:05','CNAF - Italian National Center for Research and Development (CNAF)','CECILIA',NULL,'LALL','\0',NULL,NULL,NULL),(33,'(some address)','2017-03-21 17:50:05','/C=IT/O=IGI/CN=TIERA DOWLIN','TIERA.DOWLIN.33@voms.test.io','2018-03-21 17:50:05','CNAF - Italian National Center for Research and Development (CNAF)','TIERA',NULL,'DOWLIN','\0',NULL,NULL,NULL),(34,'(some address)','2017-03-21 17:50:05','/C=IT/O=IGI/CN=DETRA TATAR','DETRA.TATAR.34@voms.test.io','2018-03-21 17:50:05','CNAF - Italian National Center for Research and Development (CNAF)','DETRA',NULL,'TATAR','\0',NULL,NULL,NULL),(35,'(some address)','2017-03-21 17:50:06','/C=IT/O=IGI/CN=JULES TOTTEN','JULES.TOTTEN.35@voms.test.io','2018-03-21 17:50:06','CNAF - Italian National Center for Research and Development (CNAF)','JULES',NULL,'TOTTEN','\0',NULL,NULL,NULL),(36,'(some address)','2017-03-21 17:50:07','/C=IT/O=IGI/CN=DORTHA HOBDAY','DORTHA.HOBDAY.36@voms.test.io','2018-03-21 17:50:07','CNAF - Italian National Center for Research and Development (CNAF)','DORTHA',NULL,'HOBDAY','\0',NULL,NULL,NULL),(37,'(some address)','2017-03-21 17:50:08','/C=IT/O=IGI/CN=BERENICE ORLOWSKY','BERENICE.ORLOWSKY.37@voms.test.io','2018-03-21 17:50:08','CNAF - Italian National Center for Research and Development (CNAF)','BERENICE',NULL,'ORLOWSKY','\0',NULL,NULL,NULL),(38,'(some address)','2017-03-21 17:50:08','/C=IT/O=IGI/CN=BRITTANEY DENIER','BRITTANEY.DENIER.38@voms.test.io','2018-03-21 17:50:08','CNAF - Italian National Center for Research and Development (CNAF)','BRITTANEY',NULL,'DENIER','\0',NULL,NULL,NULL),(39,'(some address)','2017-03-21 17:50:08','/C=IT/O=IGI/CN=ALITA HONTZ','ALITA.HONTZ.39@voms.test.io','2018-03-21 17:50:08','CNAF - Italian National Center for Research and Development (CNAF)','ALITA',NULL,'HONTZ','\0',NULL,NULL,NULL),(40,'(some address)','2017-03-21 17:50:09','/C=IT/O=IGI/CN=FREEMAN KOBIE','FREEMAN.KOBIE.40@voms.test.io','2018-03-21 17:50:09','CNAF - Italian National Center for Research and Development (CNAF)','FREEMAN',NULL,'KOBIE','\0',NULL,NULL,NULL),(41,'(some address)','2017-03-21 17:50:09','/C=IT/O=IGI/CN=LEEANNA VOIGT','LEEANNA.VOIGT.41@voms.test.io','2018-03-21 17:50:09','CNAF - Italian National Center for Research and Development (CNAF)','LEEANNA',NULL,'VOIGT','\0',NULL,NULL,NULL),(42,'(some address)','2017-03-21 17:50:10','/C=IT/O=IGI/CN=JOSH PAULINA','JOSH.PAULINA.42@voms.test.io','2018-03-21 17:50:10','CNAF - Italian National Center for Research and Development (CNAF)','JOSH',NULL,'PAULINA','\0',NULL,NULL,NULL),(43,'(some address)','2017-03-21 17:50:10','/C=IT/O=IGI/CN=DACIA SHAUB','DACIA.SHAUB.43@voms.test.io','2018-03-21 17:50:10','CNAF - Italian National Center for Research and Development (CNAF)','DACIA',NULL,'SHAUB','\0',NULL,NULL,NULL),(44,'(some address)','2017-03-21 17:50:11','/C=IT/O=IGI/CN=FREDERICK WIRTA','FREDERICK.WIRTA.44@voms.test.io','2018-03-21 17:50:11','CNAF - Italian National Center for Research and Development (CNAF)','FREDERICK',NULL,'WIRTA','\0',NULL,NULL,NULL),(45,'(some address)','2017-03-21 17:50:11','/C=IT/O=IGI/CN=TRICIA WIESER','TRICIA.WIESER.45@voms.test.io','2018-03-21 17:50:11','CNAF - Italian National Center for Research and Development (CNAF)','TRICIA',NULL,'WIESER','\0',NULL,NULL,NULL),(46,'(some address)','2017-03-21 17:50:11','/C=IT/O=IGI/CN=ELIN GOSTOMSKI','ELIN.GOSTOMSKI.46@voms.test.io','2018-03-21 17:50:11','CNAF - Italian National Center for Research and Development (CNAF)','ELIN',NULL,'GOSTOMSKI','\0',NULL,NULL,NULL),(47,'(some address)','2017-03-21 17:50:12','/C=IT/O=IGI/CN=FREDRICK LINNELL','FREDRICK.LINNELL.47@voms.test.io','2018-03-21 17:50:12','CNAF - Italian National Center for Research and Development (CNAF)','FREDRICK',NULL,'LINNELL','\0',NULL,NULL,NULL),(48,'(some address)','2017-03-21 17:50:12','/C=IT/O=IGI/CN=LYNN RIGHTMYER','LYNN.RIGHTMYER.48@voms.test.io','2018-03-21 17:50:12','CNAF - Italian National Center for Research and Development (CNAF)','LYNN',NULL,'RIGHTMYER','\0',NULL,NULL,NULL),(49,'(some address)','2017-03-21 17:50:12','/C=IT/O=IGI/CN=SIMA WEST','SIMA.WEST.49@voms.test.io','2018-03-21 17:50:12','CNAF - Italian National Center for Research and Development (CNAF)','SIMA',NULL,'WEST','\0',NULL,NULL,NULL),(50,'(some address)','2017-03-21 17:50:13','/C=IT/O=IGI/CN=YUKIKO DONOHO','YUKIKO.DONOHO.50@voms.test.io','2018-03-21 17:50:13','CNAF - Italian National Center for Research and Development (CNAF)','YUKIKO',NULL,'DONOHO','\0',NULL,NULL,NULL),(51,'(some address)','2017-03-21 17:50:13','/C=IT/O=IGI/CN=LASHONDA WESTHOUSE','LASHONDA.WESTHOUSE.51@voms.test.io','2018-03-21 17:50:13','CNAF - Italian National Center for Research and Development (CNAF)','LASHONDA',NULL,'WESTHOUSE','\0',NULL,NULL,NULL),(52,'(some address)','2017-03-21 17:50:14','/C=IT/O=IGI/CN=CARMON PARLOR','CARMON.PARLOR.52@voms.test.io','2018-03-21 17:50:14','CNAF - Italian National Center for Research and Development (CNAF)','CARMON',NULL,'PARLOR','\0',NULL,NULL,NULL),(53,'(some address)','2017-03-21 17:50:14','/C=IT/O=IGI/CN=BESS SWETT','BESS.SWETT.53@voms.test.io','2018-03-21 17:50:14','CNAF - Italian National Center for Research and Development (CNAF)','BESS',NULL,'SWETT','\0',NULL,NULL,NULL),(54,'(some address)','2017-03-21 17:50:14','/C=IT/O=IGI/CN=JACKSON LEDDON','JACKSON.LEDDON.54@voms.test.io','2018-03-21 17:50:14','CNAF - Italian National Center for Research and Development (CNAF)','JACKSON',NULL,'LEDDON','\0',NULL,NULL,NULL),(55,'(some address)','2017-03-21 17:50:15','/C=IT/O=IGI/CN=GENNA HANISKO','GENNA.HANISKO.55@voms.test.io','2018-03-21 17:50:15','CNAF - Italian National Center for Research and Development (CNAF)','GENNA',NULL,'HANISKO','\0',NULL,NULL,NULL),(56,'(some address)','2017-03-21 17:50:15','/C=IT/O=IGI/CN=JUDIE WICKINGS','JUDIE.WICKINGS.56@voms.test.io','2018-03-21 17:50:15','CNAF - Italian National Center for Research and Development (CNAF)','JUDIE',NULL,'WICKINGS','\0',NULL,NULL,NULL),(57,'(some address)','2017-03-21 17:50:16','/C=IT/O=IGI/CN=KATHLENE SCHNECKLOTH','KATHLENE.SCHNECKLOTH.57@voms.test.io','2018-03-21 17:50:16','CNAF - Italian National Center for Research and Development (CNAF)','KATHLENE',NULL,'SCHNECKLOTH','\0',NULL,NULL,NULL),(58,'(some address)','2017-03-21 17:50:16','/C=IT/O=IGI/CN=OTIS TOPLK','OTIS.TOPLK.58@voms.test.io','2018-03-21 17:50:16','CNAF - Italian National Center for Research and Development (CNAF)','OTIS',NULL,'TOPLK','\0',NULL,NULL,NULL),(59,'(some address)','2017-03-21 17:50:16','/C=IT/O=IGI/CN=BERNARDO DEISHER','BERNARDO.DEISHER.59@voms.test.io','2018-03-21 17:50:16','CNAF - Italian National Center for Research and Development (CNAF)','BERNARDO',NULL,'DEISHER','\0',NULL,NULL,NULL),(60,'(some address)','2017-03-21 17:50:17','/C=IT/O=IGI/CN=LIZ WILCINSKI','LIZ.WILCINSKI.60@voms.test.io','2018-03-21 17:50:17','CNAF - Italian National Center for Research and Development (CNAF)','LIZ',NULL,'WILCINSKI','\0',NULL,NULL,NULL),(61,'(some address)','2017-03-21 17:50:17','/C=IT/O=IGI/CN=CHU KURLAND','CHU.KURLAND.61@voms.test.io','2018-03-21 17:50:17','CNAF - Italian National Center for Research and Development (CNAF)','CHU',NULL,'KURLAND','\0',NULL,NULL,NULL),(62,'(some address)','2017-03-21 17:50:17','/C=IT/O=IGI/CN=VAL KAUFFMANN','VAL.KAUFFMANN.62@voms.test.io','2018-03-21 17:50:17','CNAF - Italian National Center for Research and Development (CNAF)','VAL',NULL,'KAUFFMANN','\0',NULL,NULL,NULL),(63,'(some address)','2017-03-21 17:50:18','/C=IT/O=IGI/CN=JOEY FREIMUTH','JOEY.FREIMUTH.63@voms.test.io','2018-03-21 17:50:18','CNAF - Italian National Center for Research and Development (CNAF)','JOEY',NULL,'FREIMUTH','\0',NULL,NULL,NULL),(64,'(some address)','2017-03-21 17:50:18','/C=IT/O=IGI/CN=CHANCE BARRO','CHANCE.BARRO.64@voms.test.io','2018-03-21 17:50:18','CNAF - Italian National Center for Research and Development (CNAF)','CHANCE',NULL,'BARRO','\0',NULL,NULL,NULL),(65,'(some address)','2017-03-21 17:50:19','/C=IT/O=IGI/CN=VI SZWARC','VI.SZWARC.65@voms.test.io','2018-03-21 17:50:19','CNAF - Italian National Center for Research and Development (CNAF)','VI',NULL,'SZWARC','\0',NULL,NULL,NULL),(66,'(some address)','2017-03-21 17:50:19','/C=IT/O=IGI/CN=CARITA ABT','CARITA.ABT.66@voms.test.io','2018-03-21 17:50:19','CNAF - Italian National Center for Research and Development (CNAF)','CARITA',NULL,'ABT','\0',NULL,NULL,NULL),(67,'(some address)','2017-03-21 17:50:20','/C=IT/O=IGI/CN=COURTNEY VEIGEL','COURTNEY.VEIGEL.67@voms.test.io','2018-03-21 17:50:20','CNAF - Italian National Center for Research and Development (CNAF)','COURTNEY',NULL,'VEIGEL','\0',NULL,NULL,NULL),(68,'(some address)','2017-03-21 17:50:21','/C=IT/O=IGI/CN=ALDA MANGUS','ALDA.MANGUS.68@voms.test.io','2018-03-21 17:50:21','CNAF - Italian National Center for Research and Development (CNAF)','ALDA',NULL,'MANGUS','\0',NULL,NULL,NULL),(69,'(some address)','2017-03-21 17:50:21','/C=IT/O=IGI/CN=BERTHA MAUFFRAY','BERTHA.MAUFFRAY.69@voms.test.io','2018-03-21 17:50:21','CNAF - Italian National Center for Research and Development (CNAF)','BERTHA',NULL,'MAUFFRAY','\0',NULL,NULL,NULL),(70,'(some address)','2017-03-21 17:50:22','/C=IT/O=IGI/CN=PAULITA DOSTIE','PAULITA.DOSTIE.70@voms.test.io','2018-03-21 17:50:22','CNAF - Italian National Center for Research and Development (CNAF)','PAULITA',NULL,'DOSTIE','\0',NULL,NULL,NULL),(71,'(some address)','2017-03-21 17:50:22','/C=IT/O=IGI/CN=NELLIE BURKHARD','NELLIE.BURKHARD.71@voms.test.io','2018-03-21 17:50:22','CNAF - Italian National Center for Research and Development (CNAF)','NELLIE',NULL,'BURKHARD','\0',NULL,NULL,NULL),(72,'(some address)','2017-03-21 17:50:23','/C=IT/O=IGI/CN=XOCHITL FELLEMAN','XOCHITL.FELLEMAN.72@voms.test.io','2018-03-21 17:50:23','CNAF - Italian National Center for Research and Development (CNAF)','XOCHITL',NULL,'FELLEMAN','\0',NULL,NULL,NULL),(73,'(some address)','2017-03-21 17:50:23','/C=IT/O=IGI/CN=KEN OBRADOVICH','KEN.OBRADOVICH.73@voms.test.io','2018-03-21 17:50:23','CNAF - Italian National Center for Research and Development (CNAF)','KEN',NULL,'OBRADOVICH','\0',NULL,NULL,NULL),(74,'(some address)','2017-03-21 17:50:24','/C=IT/O=IGI/CN=WANITA DARRAH','WANITA.DARRAH.74@voms.test.io','2018-03-21 17:50:24','CNAF - Italian National Center for Research and Development (CNAF)','WANITA',NULL,'DARRAH','\0',NULL,NULL,NULL),(75,'(some address)','2017-03-21 17:50:24','/C=IT/O=IGI/CN=WILHELMINA MONARREZ','WILHELMINA.MONARREZ.75@voms.test.io','2018-03-21 17:50:24','CNAF - Italian National Center for Research and Development (CNAF)','WILHELMINA',NULL,'MONARREZ','\0',NULL,NULL,NULL),(76,'(some address)','2017-03-21 17:50:24','/C=IT/O=IGI/CN=LETA STENBERG','LETA.STENBERG.76@voms.test.io','2018-03-21 17:50:24','CNAF - Italian National Center for Research and Development (CNAF)','LETA',NULL,'STENBERG','\0',NULL,NULL,NULL),(77,'(some address)','2017-03-21 17:50:25','/C=IT/O=IGI/CN=BERT DEODATO','BERT.DEODATO.77@voms.test.io','2018-03-21 17:50:25','CNAF - Italian National Center for Research and Development (CNAF)','BERT',NULL,'DEODATO','\0',NULL,NULL,NULL),(78,'(some address)','2017-03-21 17:50:25','/C=IT/O=IGI/CN=IRMA LANOIE','IRMA.LANOIE.78@voms.test.io','2018-03-21 17:50:25','CNAF - Italian National Center for Research and Development (CNAF)','IRMA',NULL,'LANOIE','\0',NULL,NULL,NULL),(79,'(some address)','2017-03-21 17:50:26','/C=IT/O=IGI/CN=OTIS FLATTERY','OTIS.FLATTERY.79@voms.test.io','2018-03-21 17:50:26','CNAF - Italian National Center for Research and Development (CNAF)','OTIS',NULL,'FLATTERY','\0',NULL,NULL,NULL),(80,'(some address)','2017-03-21 17:50:26','/C=IT/O=IGI/CN=NOBUKO LAITE','NOBUKO.LAITE.80@voms.test.io','2018-03-21 17:50:26','CNAF - Italian National Center for Research and Development (CNAF)','NOBUKO',NULL,'LAITE','\0',NULL,NULL,NULL),(81,'(some address)','2017-03-21 17:50:26','/C=IT/O=IGI/CN=JED CATTS','JED.CATTS.81@voms.test.io','2018-03-21 17:50:26','CNAF - Italian National Center for Research and Development (CNAF)','JED',NULL,'CATTS','\0',NULL,NULL,NULL),(82,'(some address)','2017-03-21 17:50:27','/C=IT/O=IGI/CN=PAUL BOHLER','PAUL.BOHLER.82@voms.test.io','2018-03-21 17:50:27','CNAF - Italian National Center for Research and Development (CNAF)','PAUL',NULL,'BOHLER','\0',NULL,NULL,NULL),(83,'(some address)','2017-03-21 17:50:27','/C=IT/O=IGI/CN=CHANCE SAVEL','CHANCE.SAVEL.83@voms.test.io','2018-03-21 17:50:27','CNAF - Italian National Center for Research and Development (CNAF)','CHANCE',NULL,'SAVEL','\0',NULL,NULL,NULL),(84,'(some address)','2017-03-21 17:50:28','/C=IT/O=IGI/CN=TIJUANA CABBLE','TIJUANA.CABBLE.84@voms.test.io','2018-03-21 17:50:28','CNAF - Italian National Center for Research and Development (CNAF)','TIJUANA',NULL,'CABBLE','\0',NULL,NULL,NULL),(85,'(some address)','2017-03-21 17:50:29','/C=IT/O=IGI/CN=AZZIE TORELLI','AZZIE.TORELLI.85@voms.test.io','2018-03-21 17:50:29','CNAF - Italian National Center for Research and Development (CNAF)','AZZIE',NULL,'TORELLI','\0',NULL,NULL,NULL),(86,'(some address)','2017-03-21 17:50:29','/C=IT/O=IGI/CN=CARYLON VERSTRAETE','CARYLON.VERSTRAETE.86@voms.test.io','2018-03-21 17:50:29','CNAF - Italian National Center for Research and Development (CNAF)','CARYLON',NULL,'VERSTRAETE','\0',NULL,NULL,NULL),(87,'(some address)','2017-03-21 17:50:30','/C=IT/O=IGI/CN=WAVA BENKEN','WAVA.BENKEN.87@voms.test.io','2018-03-21 17:50:30','CNAF - Italian National Center for Research and Development (CNAF)','WAVA',NULL,'BENKEN','\0',NULL,NULL,NULL),(88,'(some address)','2017-03-21 17:50:30','/C=IT/O=IGI/CN=VENNIE DOMENICK','VENNIE.DOMENICK.88@voms.test.io','2018-03-21 17:50:30','CNAF - Italian National Center for Research and Development (CNAF)','VENNIE',NULL,'DOMENICK','\0',NULL,NULL,NULL),(89,'(some address)','2017-03-21 17:50:30','/C=IT/O=IGI/CN=FREDDA HYTEN','FREDDA.HYTEN.89@voms.test.io','2018-03-21 17:50:30','CNAF - Italian National Center for Research and Development (CNAF)','FREDDA',NULL,'HYTEN','\0',NULL,NULL,NULL),(90,'(some address)','2017-03-21 17:50:31','/C=IT/O=IGI/CN=HAYDEE BZHYAN','HAYDEE.BZHYAN.90@voms.test.io','2018-03-21 17:50:31','CNAF - Italian National Center for Research and Development (CNAF)','HAYDEE',NULL,'BZHYAN','\0',NULL,NULL,NULL),(91,'(some address)','2017-03-21 17:50:31','/C=IT/O=IGI/CN=ELIJAH BURDELL','ELIJAH.BURDELL.91@voms.test.io','2018-03-21 17:50:31','CNAF - Italian National Center for Research and Development (CNAF)','ELIJAH',NULL,'BURDELL','\0',NULL,NULL,NULL),(92,'(some address)','2017-03-21 17:50:32','/C=IT/O=IGI/CN=BETHANIE CASTILLA','BETHANIE.CASTILLA.92@voms.test.io','2018-03-21 17:50:32','CNAF - Italian National Center for Research and Development (CNAF)','BETHANIE',NULL,'CASTILLA','\0',NULL,NULL,NULL),(93,'(some address)','2017-03-21 17:50:32','/C=IT/O=IGI/CN=LESLIE HANCOCK','LESLIE.HANCOCK.93@voms.test.io','2018-03-21 17:50:32','CNAF - Italian National Center for Research and Development (CNAF)','LESLIE',NULL,'HANCOCK','\0',NULL,NULL,NULL),(94,'(some address)','2017-03-21 17:50:32','/C=IT/O=IGI/CN=XENIA HAULBROOK','XENIA.HAULBROOK.94@voms.test.io','2018-03-21 17:50:32','CNAF - Italian National Center for Research and Development (CNAF)','XENIA',NULL,'HAULBROOK','\0',NULL,NULL,NULL),(95,'(some address)','2017-03-21 17:50:33','/C=IT/O=IGI/CN=YUKO CROMBIE','YUKO.CROMBIE.95@voms.test.io','2018-03-21 17:50:33','CNAF - Italian National Center for Research and Development (CNAF)','YUKO',NULL,'CROMBIE','\0',NULL,NULL,NULL),(96,'(some address)','2017-03-21 17:50:33','/C=IT/O=IGI/CN=JALEESA HANIFAN','JALEESA.HANIFAN.96@voms.test.io','2018-03-21 17:50:33','CNAF - Italian National Center for Research and Development (CNAF)','JALEESA',NULL,'HANIFAN','\0',NULL,NULL,NULL),(97,'(some address)','2017-03-21 17:50:34','/C=IT/O=IGI/CN=KRYSTIN LYBRAND','KRYSTIN.LYBRAND.97@voms.test.io','2018-03-21 17:50:34','CNAF - Italian National Center for Research and Development (CNAF)','KRYSTIN',NULL,'LYBRAND','\0',NULL,NULL,NULL),(98,'(some address)','2017-03-21 17:50:34','/C=IT/O=IGI/CN=KORY MCPARLAND','KORY.MCPARLAND.98@voms.test.io','2018-03-21 17:50:34','CNAF - Italian National Center for Research and Development (CNAF)','KORY',NULL,'MCPARLAND','\0',NULL,NULL,NULL),(99,'(some address)','2017-03-21 17:50:34','/C=IT/O=IGI/CN=WAN SAMMON','WAN.SAMMON.99@voms.test.io','2018-03-21 17:50:34','CNAF - Italian National Center for Research and Development (CNAF)','WAN',NULL,'SAMMON','\0',NULL,NULL,NULL),(100,'(some address)','2017-03-21 17:50:35','/C=IT/O=IGI/CN=HANH ATCITTY','HANH.ATCITTY.100@voms.test.io','2018-03-21 17:50:35','CNAF - Italian National Center for Research and Development (CNAF)','HANH',NULL,'ATCITTY','\0',NULL,NULL,NULL),(101,'(some address)','2017-03-21 17:50:35','/C=IT/O=IGI/CN=ANGELIC URBINA','ANGELIC.URBINA.101@voms.test.io','2018-03-21 17:50:35','CNAF - Italian National Center for Research and Development (CNAF)','ANGELIC',NULL,'URBINA','\0',NULL,NULL,NULL),(102,'(some address)','2017-03-21 17:50:36','/C=IT/O=IGI/CN=AUSTIN CARABAJAL','AUSTIN.CARABAJAL.102@voms.test.io','2018-03-21 17:50:36','CNAF - Italian National Center for Research and Development (CNAF)','AUSTIN',NULL,'CARABAJAL','\0',NULL,NULL,NULL),(103,'(some address)','2017-03-21 17:50:36','/C=IT/O=IGI/CN=INGA DINGFELDER','INGA.DINGFELDER.103@voms.test.io','2018-03-21 17:50:36','CNAF - Italian National Center for Research and Development (CNAF)','INGA',NULL,'DINGFELDER','\0',NULL,NULL,NULL),(104,'(some address)','2017-03-21 17:50:37','/C=IT/O=IGI/CN=LIVIA ASHBACHER','LIVIA.ASHBACHER.104@voms.test.io','2018-03-21 17:50:37','CNAF - Italian National Center for Research and Development (CNAF)','LIVIA',NULL,'ASHBACHER','\0',NULL,NULL,NULL),(105,'(some address)','2017-03-21 17:50:38','/C=IT/O=IGI/CN=BROOKE LEBEDEFF','BROOKE.LEBEDEFF.105@voms.test.io','2018-03-21 17:50:38','CNAF - Italian National Center for Research and Development (CNAF)','BROOKE',NULL,'LEBEDEFF','\0',NULL,NULL,NULL),(106,'(some address)','2017-03-21 17:50:38','/C=IT/O=IGI/CN=SUNSHINE BUTTARO','SUNSHINE.BUTTARO.106@voms.test.io','2018-03-21 17:50:38','CNAF - Italian National Center for Research and Development (CNAF)','SUNSHINE',NULL,'BUTTARO','\0',NULL,NULL,NULL),(107,'(some address)','2017-03-21 17:50:39','/C=IT/O=IGI/CN=TWYLA TIBWELL','TWYLA.TIBWELL.107@voms.test.io','2018-03-21 17:50:39','CNAF - Italian National Center for Research and Development (CNAF)','TWYLA',NULL,'TIBWELL','\0',NULL,NULL,NULL),(108,'(some address)','2017-03-21 17:50:39','/C=IT/O=IGI/CN=MILLARD CARAVELLA','MILLARD.CARAVELLA.108@voms.test.io','2018-03-21 17:50:39','CNAF - Italian National Center for Research and Development (CNAF)','MILLARD',NULL,'CARAVELLA','\0',NULL,NULL,NULL),(109,'(some address)','2017-03-21 17:50:39','/C=IT/O=IGI/CN=MARGURITE AYOOB','MARGURITE.AYOOB.109@voms.test.io','2018-03-21 17:50:39','CNAF - Italian National Center for Research and Development (CNAF)','MARGURITE',NULL,'AYOOB','\0',NULL,NULL,NULL),(110,'(some address)','2017-03-21 17:50:40','/C=IT/O=IGI/CN=MARIKO TENN','MARIKO.TENN.110@voms.test.io','2018-03-21 17:50:40','CNAF - Italian National Center for Research and Development (CNAF)','MARIKO',NULL,'TENN','\0',NULL,NULL,NULL),(111,'(some address)','2017-03-21 17:50:40','/C=IT/O=IGI/CN=JINNY KRUGER','JINNY.KRUGER.111@voms.test.io','2018-03-21 17:50:40','CNAF - Italian National Center for Research and Development (CNAF)','JINNY',NULL,'KRUGER','\0',NULL,NULL,NULL),(112,'(some address)','2017-03-21 17:50:41','/C=IT/O=IGI/CN=RETHA PINCHBECK','RETHA.PINCHBECK.112@voms.test.io','2018-03-21 17:50:41','CNAF - Italian National Center for Research and Development (CNAF)','RETHA',NULL,'PINCHBECK','\0',NULL,NULL,NULL),(113,'(some address)','2017-03-21 17:50:41','/C=IT/O=IGI/CN=KIMBERY LOBDELL','KIMBERY.LOBDELL.113@voms.test.io','2018-03-21 17:50:41','CNAF - Italian National Center for Research and Development (CNAF)','KIMBERY',NULL,'LOBDELL','\0',NULL,NULL,NULL),(114,'(some address)','2017-03-21 17:50:41','/C=IT/O=IGI/CN=SHIRELY BORGATTI','SHIRELY.BORGATTI.114@voms.test.io','2018-03-21 17:50:41','CNAF - Italian National Center for Research and Development (CNAF)','SHIRELY',NULL,'BORGATTI','\0',NULL,NULL,NULL),(115,'(some address)','2017-03-21 17:50:42','/C=IT/O=IGI/CN=TODD OKKEN','TODD.OKKEN.115@voms.test.io','2018-03-21 17:50:42','CNAF - Italian National Center for Research and Development (CNAF)','TODD',NULL,'OKKEN','\0',NULL,NULL,NULL),(116,'(some address)','2017-03-21 17:50:42','/C=IT/O=IGI/CN=RUPERT MONTALBO','RUPERT.MONTALBO.116@voms.test.io','2018-03-21 17:50:42','CNAF - Italian National Center for Research and Development (CNAF)','RUPERT',NULL,'MONTALBO','\0',NULL,NULL,NULL),(117,'(some address)','2017-03-21 17:50:43','/C=IT/O=IGI/CN=JIMMIE ISRAELSEN','JIMMIE.ISRAELSEN.117@voms.test.io','2018-03-21 17:50:43','CNAF - Italian National Center for Research and Development (CNAF)','JIMMIE',NULL,'ISRAELSEN','\0',NULL,NULL,NULL),(118,'(some address)','2017-03-21 17:50:43','/C=IT/O=IGI/CN=STEPANIE VOLNER','STEPANIE.VOLNER.118@voms.test.io','2018-03-21 17:50:43','CNAF - Italian National Center for Research and Development (CNAF)','STEPANIE',NULL,'VOLNER','\0',NULL,NULL,NULL),(119,'(some address)','2017-03-21 17:50:43','/C=IT/O=IGI/CN=ULRIKE KEMPSON','ULRIKE.KEMPSON.119@voms.test.io','2018-03-21 17:50:43','CNAF - Italian National Center for Research and Development (CNAF)','ULRIKE',NULL,'KEMPSON','\0',NULL,NULL,NULL),(120,'(some address)','2017-03-21 17:50:44','/C=IT/O=IGI/CN=JINA MEGO','JINA.MEGO.120@voms.test.io','2018-03-21 17:50:44','CNAF - Italian National Center for Research and Development (CNAF)','JINA',NULL,'MEGO','\0',NULL,NULL,NULL),(121,'(some address)','2017-03-21 17:50:44','/C=IT/O=IGI/CN=VANNA JOOS','VANNA.JOOS.121@voms.test.io','2018-03-21 17:50:44','CNAF - Italian National Center for Research and Development (CNAF)','VANNA',NULL,'JOOS','\0',NULL,NULL,NULL),(122,'(some address)','2017-03-21 17:50:45','/C=IT/O=IGI/CN=TONA RAROGAL','TONA.RAROGAL.122@voms.test.io','2018-03-21 17:50:45','CNAF - Italian National Center for Research and Development (CNAF)','TONA',NULL,'RAROGAL','\0',NULL,NULL,NULL),(123,'(some address)','2017-03-21 17:50:45','/C=IT/O=IGI/CN=BRYAN HEMERLY','BRYAN.HEMERLY.123@voms.test.io','2018-03-21 17:50:45','CNAF - Italian National Center for Research and Development (CNAF)','BRYAN',NULL,'HEMERLY','\0',NULL,NULL,NULL),(124,'(some address)','2017-03-21 17:50:46','/C=IT/O=IGI/CN=ALEEN DARCO','ALEEN.DARCO.124@voms.test.io','2018-03-21 17:50:46','CNAF - Italian National Center for Research and Development (CNAF)','ALEEN',NULL,'DARCO','\0',NULL,NULL,NULL),(125,'(some address)','2017-03-21 17:50:46','/C=IT/O=IGI/CN=MARGUERITE MITCHLER','MARGUERITE.MITCHLER.125@voms.test.io','2018-03-21 17:50:46','CNAF - Italian National Center for Research and Development (CNAF)','MARGUERITE',NULL,'MITCHLER','\0',NULL,NULL,NULL),(126,'(some address)','2017-03-21 17:50:47','/C=IT/O=IGI/CN=ELLENA BEICHNER','ELLENA.BEICHNER.126@voms.test.io','2018-03-21 17:50:47','CNAF - Italian National Center for Research and Development (CNAF)','ELLENA',NULL,'BEICHNER','\0',NULL,NULL,NULL),(127,'(some address)','2017-03-21 17:50:47','/C=IT/O=IGI/CN=PEGGY DATY','PEGGY.DATY.127@voms.test.io','2018-03-21 17:50:47','CNAF - Italian National Center for Research and Development (CNAF)','PEGGY',NULL,'DATY','\0',NULL,NULL,NULL),(128,'(some address)','2017-03-21 17:50:48','/C=IT/O=IGI/CN=ELNORA HOMBY','ELNORA.HOMBY.128@voms.test.io','2018-03-21 17:50:48','CNAF - Italian National Center for Research and Development (CNAF)','ELNORA',NULL,'HOMBY','\0',NULL,NULL,NULL),(129,'(some address)','2017-03-21 17:50:49','/C=IT/O=IGI/CN=DREAMA LUCKENBAUGH','DREAMA.LUCKENBAUGH.129@voms.test.io','2018-03-21 17:50:49','CNAF - Italian National Center for Research and Development (CNAF)','DREAMA',NULL,'LUCKENBAUGH','\0',NULL,NULL,NULL),(130,'(some address)','2017-03-21 17:50:49','/C=IT/O=IGI/CN=HORTENCIA TICA','HORTENCIA.TICA.130@voms.test.io','2018-03-21 17:50:49','CNAF - Italian National Center for Research and Development (CNAF)','HORTENCIA',NULL,'TICA','\0',NULL,NULL,NULL),(131,'(some address)','2017-03-21 17:50:49','/C=IT/O=IGI/CN=OTTO BEUMER','OTTO.BEUMER.131@voms.test.io','2018-03-21 17:50:49','CNAF - Italian National Center for Research and Development (CNAF)','OTTO',NULL,'BEUMER','\0',NULL,NULL,NULL),(132,'(some address)','2017-03-21 17:50:50','/C=IT/O=IGI/CN=ZACHARY BIHM','ZACHARY.BIHM.132@voms.test.io','2018-03-21 17:50:50','CNAF - Italian National Center for Research and Development (CNAF)','ZACHARY',NULL,'BIHM','\0',NULL,NULL,NULL),(133,'(some address)','2017-03-21 17:50:50','/C=IT/O=IGI/CN=ANNMARIE MUSILLI','ANNMARIE.MUSILLI.133@voms.test.io','2018-03-21 17:50:50','CNAF - Italian National Center for Research and Development (CNAF)','ANNMARIE',NULL,'MUSILLI','\0',NULL,NULL,NULL),(134,'(some address)','2017-03-21 17:50:50','/C=IT/O=IGI/CN=SAL LUTGEN','SAL.LUTGEN.134@voms.test.io','2018-03-21 17:50:50','CNAF - Italian National Center for Research and Development (CNAF)','SAL',NULL,'LUTGEN','\0',NULL,NULL,NULL),(135,'(some address)','2017-03-21 17:50:51','/C=IT/O=IGI/CN=DAMON HUMMINGBIRD','DAMON.HUMMINGBIRD.135@voms.test.io','2018-03-21 17:50:51','CNAF - Italian National Center for Research and Development (CNAF)','DAMON',NULL,'HUMMINGBIRD','\0',NULL,NULL,NULL),(136,'(some address)','2017-03-21 17:50:51','/C=IT/O=IGI/CN=GRACIE PADIONG','GRACIE.PADIONG.136@voms.test.io','2018-03-21 17:50:51','CNAF - Italian National Center for Research and Development (CNAF)','GRACIE',NULL,'PADIONG','\0',NULL,NULL,NULL),(137,'(some address)','2017-03-21 17:50:52','/C=IT/O=IGI/CN=MARSHALL PORTEUS','MARSHALL.PORTEUS.137@voms.test.io','2018-03-21 17:50:52','CNAF - Italian National Center for Research and Development (CNAF)','MARSHALL',NULL,'PORTEUS','\0',NULL,NULL,NULL),(138,'(some address)','2017-03-21 17:50:52','/C=IT/O=IGI/CN=ISIDRA CLAP','ISIDRA.CLAP.138@voms.test.io','2018-03-21 17:50:52','CNAF - Italian National Center for Research and Development (CNAF)','ISIDRA',NULL,'CLAP','\0',NULL,NULL,NULL),(139,'(some address)','2017-03-21 17:50:53','/C=IT/O=IGI/CN=CHUNG PONTONIO','CHUNG.PONTONIO.139@voms.test.io','2018-03-21 17:50:53','CNAF - Italian National Center for Research and Development (CNAF)','CHUNG',NULL,'PONTONIO','\0',NULL,NULL,NULL),(140,'(some address)','2017-03-21 17:50:53','/C=IT/O=IGI/CN=CLAUDIA GRAYSON','CLAUDIA.GRAYSON.140@voms.test.io','2018-03-21 17:50:53','CNAF - Italian National Center for Research and Development (CNAF)','CLAUDIA',NULL,'GRAYSON','\0',NULL,NULL,NULL),(141,'(some address)','2017-03-21 17:50:53','/C=IT/O=IGI/CN=JONELL POWROZNIK','JONELL.POWROZNIK.141@voms.test.io','2018-03-21 17:50:53','CNAF - Italian National Center for Research and Development (CNAF)','JONELL',NULL,'POWROZNIK','\0',NULL,NULL,NULL),(142,'(some address)','2017-03-21 17:50:54','/C=IT/O=IGI/CN=KIMBERLEE BRUMMET','KIMBERLEE.BRUMMET.142@voms.test.io','2018-03-21 17:50:54','CNAF - Italian National Center for Research and Development (CNAF)','KIMBERLEE',NULL,'BRUMMET','\0',NULL,NULL,NULL),(143,'(some address)','2017-03-21 17:50:54','/C=IT/O=IGI/CN=JEWELL DELSORDO','JEWELL.DELSORDO.143@voms.test.io','2018-03-21 17:50:54','CNAF - Italian National Center for Research and Development (CNAF)','JEWELL',NULL,'DELSORDO','\0',NULL,NULL,NULL),(144,'(some address)','2017-03-21 17:50:54','/C=IT/O=IGI/CN=FERMINA WHITNER','FERMINA.WHITNER.144@voms.test.io','2018-03-21 17:50:54','CNAF - Italian National Center for Research and Development (CNAF)','FERMINA',NULL,'WHITNER','\0',NULL,NULL,NULL),(145,'(some address)','2017-03-21 17:50:55','/C=IT/O=IGI/CN=MARTHA HOLLMANN','MARTHA.HOLLMANN.145@voms.test.io','2018-03-21 17:50:55','CNAF - Italian National Center for Research and Development (CNAF)','MARTHA',NULL,'HOLLMANN','\0',NULL,NULL,NULL),(146,'(some address)','2017-03-21 17:50:55','/C=IT/O=IGI/CN=DEIDRE HINGSTON','DEIDRE.HINGSTON.146@voms.test.io','2018-03-21 17:50:55','CNAF - Italian National Center for Research and Development (CNAF)','DEIDRE',NULL,'HINGSTON','\0',NULL,NULL,NULL),(147,'(some address)','2017-03-21 17:50:55','/C=IT/O=IGI/CN=DEWITT MOHLKE','DEWITT.MOHLKE.147@voms.test.io','2018-03-21 17:50:55','CNAF - Italian National Center for Research and Development (CNAF)','DEWITT',NULL,'MOHLKE','\0',NULL,NULL,NULL),(148,'(some address)','2017-03-21 17:50:56','/C=IT/O=IGI/CN=PETRONILA ALSANDOR','PETRONILA.ALSANDOR.148@voms.test.io','2018-03-21 17:50:56','CNAF - Italian National Center for Research and Development (CNAF)','PETRONILA',NULL,'ALSANDOR','\0',NULL,NULL,NULL),(149,'(some address)','2017-03-21 17:50:56','/C=IT/O=IGI/CN=TERI GRECH','TERI.GRECH.149@voms.test.io','2018-03-21 17:50:56','CNAF - Italian National Center for Research and Development (CNAF)','TERI',NULL,'GRECH','\0',NULL,NULL,NULL),(150,'(some address)','2017-03-21 17:50:56','/C=IT/O=IGI/CN=CLINT GOLUB','CLINT.GOLUB.150@voms.test.io','2018-03-21 17:50:56','CNAF - Italian National Center for Research and Development (CNAF)','CLINT',NULL,'GOLUB','\0',NULL,NULL,NULL),(151,'(some address)','2017-03-21 17:50:57','/C=IT/O=IGI/CN=TRULA GROTHAUS','TRULA.GROTHAUS.151@voms.test.io','2018-03-21 17:50:57','CNAF - Italian National Center for Research and Development (CNAF)','TRULA',NULL,'GROTHAUS','\0',NULL,NULL,NULL),(152,'(some address)','2017-03-21 17:50:57','/C=IT/O=IGI/CN=TORY BURDEX','TORY.BURDEX.152@voms.test.io','2018-03-21 17:50:57','CNAF - Italian National Center for Research and Development (CNAF)','TORY',NULL,'BURDEX','\0',NULL,NULL,NULL),(153,'(some address)','2017-03-21 17:50:58','/C=IT/O=IGI/CN=NELLIE RUSCHE','NELLIE.RUSCHE.153@voms.test.io','2018-03-21 17:50:58','CNAF - Italian National Center for Research and Development (CNAF)','NELLIE',NULL,'RUSCHE','\0',NULL,NULL,NULL),(154,'(some address)','2017-03-21 17:50:58','/C=IT/O=IGI/CN=BRENDA ROMON','BRENDA.ROMON.154@voms.test.io','2018-03-21 17:50:58','CNAF - Italian National Center for Research and Development (CNAF)','BRENDA',NULL,'ROMON','\0',NULL,NULL,NULL),(155,'(some address)','2017-03-21 17:50:58','/C=IT/O=IGI/CN=WARREN ZURAWIK','WARREN.ZURAWIK.155@voms.test.io','2018-03-21 17:50:58','CNAF - Italian National Center for Research and Development (CNAF)','WARREN',NULL,'ZURAWIK','\0',NULL,NULL,NULL),(156,'(some address)','2017-03-21 17:50:59','/C=IT/O=IGI/CN=JANYCE HOLJE','JANYCE.HOLJE.156@voms.test.io','2018-03-21 17:50:59','CNAF - Italian National Center for Research and Development (CNAF)','JANYCE',NULL,'HOLJE','\0',NULL,NULL,NULL),(157,'(some address)','2017-03-21 17:50:59','/C=IT/O=IGI/CN=LELIA BUSHNER','LELIA.BUSHNER.157@voms.test.io','2018-03-21 17:50:59','CNAF - Italian National Center for Research and Development (CNAF)','LELIA',NULL,'BUSHNER','\0',NULL,NULL,NULL),(158,'(some address)','2017-03-21 17:50:59','/C=IT/O=IGI/CN=CHESTER DESUE','CHESTER.DESUE.158@voms.test.io','2018-03-21 17:50:59','CNAF - Italian National Center for Research and Development (CNAF)','CHESTER',NULL,'DESUE','\0',NULL,NULL,NULL),(159,'(some address)','2017-03-21 17:51:00','/C=IT/O=IGI/CN=MELLISSA MAKINEN','MELLISSA.MAKINEN.159@voms.test.io','2018-03-21 17:51:00','CNAF - Italian National Center for Research and Development (CNAF)','MELLISSA',NULL,'MAKINEN','\0',NULL,NULL,NULL),(160,'(some address)','2017-03-21 17:51:00','/C=IT/O=IGI/CN=ADRIAN DACHS','ADRIAN.DACHS.160@voms.test.io','2018-03-21 17:51:00','CNAF - Italian National Center for Research and Development (CNAF)','ADRIAN',NULL,'DACHS','\0',NULL,NULL,NULL),(161,'(some address)','2017-03-21 17:51:00','/C=IT/O=IGI/CN=WAN COSIER','WAN.COSIER.161@voms.test.io','2018-03-21 17:51:00','CNAF - Italian National Center for Research and Development (CNAF)','WAN',NULL,'COSIER','\0',NULL,NULL,NULL),(162,'(some address)','2017-03-21 17:51:01','/C=IT/O=IGI/CN=DORATHY CARDON','DORATHY.CARDON.162@voms.test.io','2018-03-21 17:51:01','CNAF - Italian National Center for Research and Development (CNAF)','DORATHY',NULL,'CARDON','\0',NULL,NULL,NULL),(163,'(some address)','2017-03-21 17:51:01','/C=IT/O=IGI/CN=GLYNDA STARN','GLYNDA.STARN.163@voms.test.io','2018-03-21 17:51:01','CNAF - Italian National Center for Research and Development (CNAF)','GLYNDA',NULL,'STARN','\0',NULL,NULL,NULL),(164,'(some address)','2017-03-21 17:51:02','/C=IT/O=IGI/CN=MITCHELL CRIMIN','MITCHELL.CRIMIN.164@voms.test.io','2018-03-21 17:51:02','CNAF - Italian National Center for Research and Development (CNAF)','MITCHELL',NULL,'CRIMIN','\0',NULL,NULL,NULL),(165,'(some address)','2017-03-21 17:51:02','/C=IT/O=IGI/CN=KATHERIN GIRLING','KATHERIN.GIRLING.165@voms.test.io','2018-03-21 17:51:02','CNAF - Italian National Center for Research and Development (CNAF)','KATHERIN',NULL,'GIRLING','\0',NULL,NULL,NULL),(166,'(some address)','2017-03-21 17:51:02','/C=IT/O=IGI/CN=ELISHA MANSER','ELISHA.MANSER.166@voms.test.io','2018-03-21 17:51:02','CNAF - Italian National Center for Research and Development (CNAF)','ELISHA',NULL,'MANSER','\0',NULL,NULL,NULL),(167,'(some address)','2017-03-21 17:51:03','/C=IT/O=IGI/CN=ARVILLA BERTELS','ARVILLA.BERTELS.167@voms.test.io','2018-03-21 17:51:03','CNAF - Italian National Center for Research and Development (CNAF)','ARVILLA',NULL,'BERTELS','\0',NULL,NULL,NULL),(168,'(some address)','2017-03-21 17:51:03','/C=IT/O=IGI/CN=HANNAH TAMMO','HANNAH.TAMMO.168@voms.test.io','2018-03-21 17:51:03','CNAF - Italian National Center for Research and Development (CNAF)','HANNAH',NULL,'TAMMO','\0',NULL,NULL,NULL),(169,'(some address)','2017-03-21 17:51:04','/C=IT/O=IGI/CN=RUDOLF STETZ','RUDOLF.STETZ.169@voms.test.io','2018-03-21 17:51:04','CNAF - Italian National Center for Research and Development (CNAF)','RUDOLF',NULL,'STETZ','\0',NULL,NULL,NULL),(170,'(some address)','2017-03-21 17:51:04','/C=IT/O=IGI/CN=CATHARINE PAYWA','CATHARINE.PAYWA.170@voms.test.io','2018-03-21 17:51:04','CNAF - Italian National Center for Research and Development (CNAF)','CATHARINE',NULL,'PAYWA','\0',NULL,NULL,NULL),(171,'(some address)','2017-03-21 17:51:04','/C=IT/O=IGI/CN=CATALINA VANHOOSER','CATALINA.VANHOOSER.171@voms.test.io','2018-03-21 17:51:04','CNAF - Italian National Center for Research and Development (CNAF)','CATALINA',NULL,'VANHOOSER','\0',NULL,NULL,NULL),(172,'(some address)','2017-03-21 17:51:05','/C=IT/O=IGI/CN=NICOLLE VAUTOUR','NICOLLE.VAUTOUR.172@voms.test.io','2018-03-21 17:51:05','CNAF - Italian National Center for Research and Development (CNAF)','NICOLLE',NULL,'VAUTOUR','\0',NULL,NULL,NULL),(173,'(some address)','2017-03-21 17:51:05','/C=IT/O=IGI/CN=ROSELIA ERDMANN','ROSELIA.ERDMANN.173@voms.test.io','2018-03-21 17:51:05','CNAF - Italian National Center for Research and Development (CNAF)','ROSELIA',NULL,'ERDMANN','\0',NULL,NULL,NULL),(174,'(some address)','2017-03-21 17:51:05','/C=IT/O=IGI/CN=SLYVIA BEADNELL','SLYVIA.BEADNELL.174@voms.test.io','2018-03-21 17:51:05','CNAF - Italian National Center for Research and Development (CNAF)','SLYVIA',NULL,'BEADNELL','\0',NULL,NULL,NULL),(175,'(some address)','2017-03-21 17:51:06','/C=IT/O=IGI/CN=SOLEDAD RAZER','SOLEDAD.RAZER.175@voms.test.io','2018-03-21 17:51:06','CNAF - Italian National Center for Research and Development (CNAF)','SOLEDAD',NULL,'RAZER','\0',NULL,NULL,NULL),(176,'(some address)','2017-03-21 17:51:06','/C=IT/O=IGI/CN=MICHALE VRABEL','MICHALE.VRABEL.176@voms.test.io','2018-03-21 17:51:06','CNAF - Italian National Center for Research and Development (CNAF)','MICHALE',NULL,'VRABEL','\0',NULL,NULL,NULL),(177,'(some address)','2017-03-21 17:51:06','/C=IT/O=IGI/CN=RAMIRO VANGUILDER','RAMIRO.VANGUILDER.177@voms.test.io','2018-03-21 17:51:06','CNAF - Italian National Center for Research and Development (CNAF)','RAMIRO',NULL,'VANGUILDER','\0',NULL,NULL,NULL),(178,'(some address)','2017-03-21 17:51:07','/C=IT/O=IGI/CN=ISA GALLEHER','ISA.GALLEHER.178@voms.test.io','2018-03-21 17:51:07','CNAF - Italian National Center for Research and Development (CNAF)','ISA',NULL,'GALLEHER','\0',NULL,NULL,NULL),(179,'(some address)','2017-03-21 17:51:08','/C=IT/O=IGI/CN=CHRISTENA STALLEY','CHRISTENA.STALLEY.179@voms.test.io','2018-03-21 17:51:08','CNAF - Italian National Center for Research and Development (CNAF)','CHRISTENA',NULL,'STALLEY','\0',NULL,NULL,NULL),(180,'(some address)','2017-03-21 17:51:08','/C=IT/O=IGI/CN=MARILU NABARRETE','MARILU.NABARRETE.180@voms.test.io','2018-03-21 17:51:08','CNAF - Italian National Center for Research and Development (CNAF)','MARILU',NULL,'NABARRETE','\0',NULL,NULL,NULL),(181,'(some address)','2017-03-21 17:51:09','/C=IT/O=IGI/CN=MYRIAM CRONQUIST','MYRIAM.CRONQUIST.181@voms.test.io','2018-03-21 17:51:09','CNAF - Italian National Center for Research and Development (CNAF)','MYRIAM',NULL,'CRONQUIST','\0',NULL,NULL,NULL),(182,'(some address)','2017-03-21 17:51:09','/C=IT/O=IGI/CN=VICTOR VANSLYKE','VICTOR.VANSLYKE.182@voms.test.io','2018-03-21 17:51:09','CNAF - Italian National Center for Research and Development (CNAF)','VICTOR',NULL,'VANSLYKE','\0',NULL,NULL,NULL),(183,'(some address)','2017-03-21 17:51:10','/C=IT/O=IGI/CN=JACKELINE BRITT','JACKELINE.BRITT.183@voms.test.io','2018-03-21 17:51:10','CNAF - Italian National Center for Research and Development (CNAF)','JACKELINE',NULL,'BRITT','\0',NULL,NULL,NULL),(184,'(some address)','2017-03-21 17:51:10','/C=IT/O=IGI/CN=KEVIN SWOPE','KEVIN.SWOPE.184@voms.test.io','2018-03-21 17:51:10','CNAF - Italian National Center for Research and Development (CNAF)','KEVIN',NULL,'SWOPE','\0',NULL,NULL,NULL),(185,'(some address)','2017-03-21 17:51:11','/C=IT/O=IGI/CN=EMERITA SWICEGOOD','EMERITA.SWICEGOOD.185@voms.test.io','2018-03-21 17:51:11','CNAF - Italian National Center for Research and Development (CNAF)','EMERITA',NULL,'SWICEGOOD','\0',NULL,NULL,NULL),(186,'(some address)','2017-03-21 17:51:11','/C=IT/O=IGI/CN=FANNIE BUGNI','FANNIE.BUGNI.186@voms.test.io','2018-03-21 17:51:11','CNAF - Italian National Center for Research and Development (CNAF)','FANNIE',NULL,'BUGNI','\0',NULL,NULL,NULL),(187,'(some address)','2017-03-21 17:51:11','/C=IT/O=IGI/CN=TERESA SKRETOWICZ','TERESA.SKRETOWICZ.187@voms.test.io','2018-03-21 17:51:11','CNAF - Italian National Center for Research and Development (CNAF)','TERESA',NULL,'SKRETOWICZ','\0',NULL,NULL,NULL),(188,'(some address)','2017-03-21 17:51:12','/C=IT/O=IGI/CN=LASANDRA KHN','LASANDRA.KHN.188@voms.test.io','2018-03-21 17:51:12','CNAF - Italian National Center for Research and Development (CNAF)','LASANDRA',NULL,'KHN','\0',NULL,NULL,NULL),(189,'(some address)','2017-03-21 17:51:12','/C=IT/O=IGI/CN=KARIE MCVINNEY','KARIE.MCVINNEY.189@voms.test.io','2018-03-21 17:51:12','CNAF - Italian National Center for Research and Development (CNAF)','KARIE',NULL,'MCVINNEY','\0',NULL,NULL,NULL),(190,'(some address)','2017-03-21 17:51:12','/C=IT/O=IGI/CN=CRYSTLE HASSEL','CRYSTLE.HASSEL.190@voms.test.io','2018-03-21 17:51:12','CNAF - Italian National Center for Research and Development (CNAF)','CRYSTLE',NULL,'HASSEL','\0',NULL,NULL,NULL),(191,'(some address)','2017-03-21 17:51:13','/C=IT/O=IGI/CN=WILLIAN GREAM','WILLIAN.GREAM.191@voms.test.io','2018-03-21 17:51:13','CNAF - Italian National Center for Research and Development (CNAF)','WILLIAN',NULL,'GREAM','\0',NULL,NULL,NULL),(192,'(some address)','2017-03-21 17:51:13','/C=IT/O=IGI/CN=MILDRED WOJTAS','MILDRED.WOJTAS.192@voms.test.io','2018-03-21 17:51:13','CNAF - Italian National Center for Research and Development (CNAF)','MILDRED',NULL,'WOJTAS','\0',NULL,NULL,NULL),(193,'(some address)','2017-03-21 17:51:14','/C=IT/O=IGI/CN=ALISON HUBERTY','ALISON.HUBERTY.193@voms.test.io','2018-03-21 17:51:14','CNAF - Italian National Center for Research and Development (CNAF)','ALISON',NULL,'HUBERTY','\0',NULL,NULL,NULL),(194,'(some address)','2017-03-21 17:51:14','/C=IT/O=IGI/CN=DELFINA MCGARR','DELFINA.MCGARR.194@voms.test.io','2018-03-21 17:51:14','CNAF - Italian National Center for Research and Development (CNAF)','DELFINA',NULL,'MCGARR','\0',NULL,NULL,NULL),(195,'(some address)','2017-03-21 17:51:15','/C=IT/O=IGI/CN=CUC PIZZO','CUC.PIZZO.195@voms.test.io','2018-03-21 17:51:15','CNAF - Italian National Center for Research and Development (CNAF)','CUC',NULL,'PIZZO','\0',NULL,NULL,NULL),(196,'(some address)','2017-03-21 17:51:15','/C=IT/O=IGI/CN=DAKOTA BILLINGSLY','DAKOTA.BILLINGSLY.196@voms.test.io','2018-03-21 17:51:15','CNAF - Italian National Center for Research and Development (CNAF)','DAKOTA',NULL,'BILLINGSLY','\0',NULL,NULL,NULL),(197,'(some address)','2017-03-21 17:51:15','/C=IT/O=IGI/CN=NAM GUEVANA','NAM.GUEVANA.197@voms.test.io','2018-03-21 17:51:15','CNAF - Italian National Center for Research and Development (CNAF)','NAM',NULL,'GUEVANA','\0',NULL,NULL,NULL),(198,'(some address)','2017-03-21 17:51:16','/C=IT/O=IGI/CN=HYE HOGGAN','HYE.HOGGAN.198@voms.test.io','2018-03-21 17:51:16','CNAF - Italian National Center for Research and Development (CNAF)','HYE',NULL,'HOGGAN','\0',NULL,NULL,NULL),(199,'(some address)','2017-03-21 17:51:16','/C=IT/O=IGI/CN=ELFRIEDE BUETI','ELFRIEDE.BUETI.199@voms.test.io','2018-03-21 17:51:16','CNAF - Italian National Center for Research and Development (CNAF)','ELFRIEDE',NULL,'BUETI','\0',NULL,NULL,NULL),(200,'(some address)','2017-03-21 17:51:16','/C=IT/O=IGI/CN=HIRAM LAMPMAN','HIRAM.LAMPMAN.200@voms.test.io','2018-03-21 17:51:16','CNAF - Italian National Center for Research and Development (CNAF)','HIRAM',NULL,'LAMPMAN','\0',NULL,NULL,NULL); +/*!40000 ALTER TABLE `usr` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `usr_attrs` +-- + +DROP TABLE IF EXISTS `usr_attrs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `usr_attrs` ( + `a_id` bigint(20) NOT NULL, + `u_id` bigint(20) NOT NULL, + `a_value` varchar(255) DEFAULT NULL, + PRIMARY KEY (`a_id`,`u_id`), + KEY `FKA39E0E3720331206` (`u_id`), + KEY `FKA39E0E37566C2A8F` (`a_id`), + CONSTRAINT `FKA39E0E3720331206` FOREIGN KEY (`u_id`) REFERENCES `usr` (`userid`), + CONSTRAINT `FKA39E0E37566C2A8F` FOREIGN KEY (`a_id`) REFERENCES `attributes` (`a_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `usr_attrs` +-- + +LOCK TABLES `usr_attrs` WRITE; +/*!40000 ALTER TABLE `usr_attrs` DISABLE KEYS */; +INSERT INTO `usr_attrs` VALUES (1,1,'CONRAD'),(1,2,'MICHAELA'),(1,3,'TINY'),(1,4,'HAI'),(1,5,'MCKENZIE'),(1,6,'CECILY'),(1,7,'LATESHA'),(1,8,'SHAQUANA'),(1,9,'DANNIE'),(1,10,'EUNICE'),(1,11,'LAHOMA'),(1,12,'DOREEN'),(1,13,'WAI'),(1,14,'KACY'),(1,15,'ADINA'),(1,16,'ANTHONY'),(1,17,'ERIC'),(1,18,'MARX'),(1,19,'MADALINE'),(1,20,'ABEL'),(1,21,'CALLIE'),(1,22,'ABE'),(1,23,'LOUIS'),(1,24,'SHAWNNA'),(1,25,'CHAD'),(1,26,'LAKEISHA'),(1,27,'RODNEY'),(1,28,'CARLA'),(1,29,'MARLON'),(1,30,'VERTIE'),(1,31,'DELLA'),(1,32,'CECILIA'),(1,33,'TIERA'),(1,34,'DETRA'),(1,35,'JULES'),(1,36,'DORTHA'),(1,37,'BERENICE'),(1,38,'BRITTANEY'),(1,39,'ALITA'),(1,40,'FREEMAN'),(1,41,'LEEANNA'),(1,42,'JOSH'),(1,43,'DACIA'),(1,44,'FREDERICK'),(1,45,'TRICIA'),(1,46,'ELIN'),(1,47,'FREDRICK'),(1,48,'LYNN'),(1,49,'SIMA'),(1,50,'YUKIKO'),(1,51,'LASHONDA'),(1,52,'CARMON'),(1,53,'BESS'),(1,54,'JACKSON'),(1,55,'GENNA'),(1,56,'JUDIE'),(1,57,'KATHLENE'),(1,58,'OTIS'),(1,59,'BERNARDO'),(1,60,'LIZ'),(1,61,'CHU'),(1,62,'VAL'),(1,63,'JOEY'),(1,64,'CHANCE'),(1,65,'VI'),(1,66,'CARITA'),(1,67,'COURTNEY'),(1,68,'ALDA'),(1,69,'BERTHA'),(1,70,'PAULITA'),(1,71,'NELLIE'),(1,72,'XOCHITL'),(1,73,'KEN'),(1,74,'WANITA'),(1,75,'WILHELMINA'),(1,76,'LETA'),(1,77,'BERT'),(1,78,'IRMA'),(1,79,'OTIS'),(1,80,'NOBUKO'),(1,81,'JED'),(1,82,'PAUL'),(1,83,'CHANCE'),(1,84,'TIJUANA'),(1,85,'AZZIE'),(1,86,'CARYLON'),(1,87,'WAVA'),(1,88,'VENNIE'),(1,89,'FREDDA'),(1,90,'HAYDEE'),(1,91,'ELIJAH'),(1,92,'BETHANIE'),(1,93,'LESLIE'),(1,94,'XENIA'),(1,95,'YUKO'),(1,96,'JALEESA'),(1,97,'KRYSTIN'),(1,98,'KORY'),(1,99,'WAN'),(1,100,'HANH'),(1,101,'ANGELIC'),(1,102,'AUSTIN'),(1,103,'INGA'),(1,104,'LIVIA'),(1,105,'BROOKE'),(1,106,'SUNSHINE'),(1,107,'TWYLA'),(1,108,'MILLARD'),(1,109,'MARGURITE'),(1,110,'MARIKO'),(1,111,'JINNY'),(1,112,'RETHA'),(1,113,'KIMBERY'),(1,114,'SHIRELY'),(1,115,'TODD'),(1,116,'RUPERT'),(1,117,'JIMMIE'),(1,118,'STEPANIE'),(1,119,'ULRIKE'),(1,120,'JINA'),(1,121,'VANNA'),(1,122,'TONA'),(1,123,'BRYAN'),(1,124,'ALEEN'),(1,125,'MARGUERITE'),(1,126,'ELLENA'),(1,127,'PEGGY'),(1,128,'ELNORA'),(1,129,'DREAMA'),(1,130,'HORTENCIA'),(1,131,'OTTO'),(1,132,'ZACHARY'),(1,133,'ANNMARIE'),(1,134,'SAL'),(1,135,'DAMON'),(1,136,'GRACIE'),(1,137,'MARSHALL'),(1,138,'ISIDRA'),(1,139,'CHUNG'),(1,140,'CLAUDIA'),(1,141,'JONELL'),(1,142,'KIMBERLEE'),(1,143,'JEWELL'),(1,144,'FERMINA'),(1,145,'MARTHA'),(1,146,'DEIDRE'),(1,147,'DEWITT'),(1,148,'PETRONILA'),(1,149,'TERI'),(1,150,'CLINT'),(1,151,'TRULA'),(1,152,'TORY'),(1,153,'NELLIE'),(1,154,'BRENDA'),(1,155,'WARREN'),(1,156,'JANYCE'),(1,157,'LELIA'),(1,158,'CHESTER'),(1,159,'MELLISSA'),(1,160,'ADRIAN'),(1,161,'WAN'),(1,162,'DORATHY'),(1,163,'GLYNDA'),(1,164,'MITCHELL'),(1,165,'KATHERIN'),(1,166,'ELISHA'),(1,167,'ARVILLA'),(1,168,'HANNAH'),(1,169,'RUDOLF'),(1,170,'CATHARINE'),(1,171,'CATALINA'),(1,172,'NICOLLE'),(1,173,'ROSELIA'),(1,174,'SLYVIA'),(1,175,'SOLEDAD'),(1,176,'MICHALE'),(1,177,'RAMIRO'),(1,178,'ISA'),(1,179,'CHRISTENA'),(1,180,'MARILU'),(1,181,'MYRIAM'),(1,182,'VICTOR'),(1,183,'JACKELINE'),(1,184,'KEVIN'),(1,185,'EMERITA'),(1,186,'FANNIE'),(1,187,'TERESA'),(1,188,'LASANDRA'),(1,189,'KARIE'),(1,190,'CRYSTLE'),(1,191,'WILLIAN'),(1,192,'MILDRED'),(1,193,'ALISON'),(1,194,'DELFINA'),(1,195,'CUC'),(1,196,'DAKOTA'),(1,197,'NAM'),(1,198,'HYE'),(1,199,'ELFRIEDE'),(1,200,'HIRAM'); +/*!40000 ALTER TABLE `usr_attrs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `version` +-- + +DROP TABLE IF EXISTS `version`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `version` ( + `version` int(11) NOT NULL, + `admin_version` varchar(255) DEFAULT NULL, + PRIMARY KEY (`version`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `version` +-- + +LOCK TABLES `version` WRITE; +/*!40000 ALTER TABLE `version` DISABLE KEYS */; +INSERT INTO `version` VALUES (3,'3.3.3'); +/*!40000 ALTER TABLE `version` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vo_membership_req` +-- + +DROP TABLE IF EXISTS `vo_membership_req`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vo_membership_req` ( + `confirmId` varchar(255) NOT NULL, + `request_id` bigint(20) NOT NULL, + PRIMARY KEY (`request_id`), + KEY `FK28EE8AFBD75D60A4` (`request_id`), + CONSTRAINT `FK28EE8AFBD75D60A4` FOREIGN KEY (`request_id`) REFERENCES `req` (`request_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vo_membership_req` +-- + +LOCK TABLES `vo_membership_req` WRITE; +/*!40000 ALTER TABLE `vo_membership_req` DISABLE KEYS */; +/*!40000 ALTER TABLE `vo_membership_req` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2017-03-21 17:54:26 diff --git a/docker/voms-admin-server/dev/centos7/setup/tnsnames.ora b/docker/voms-admin-server/dev/centos7/setup/tnsnames.ora new file mode 100644 index 00000000..cb8e3488 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/tnsnames.ora @@ -0,0 +1,21 @@ +VOMS= +(DESCRIPTION = + (ADDRESS_LIST = + (ADDRESS = (PROTOCOL = TCP)(HOST = voms-db-02.cr.cnaf.infn.it)(PORT = 1521)) + ) + (CONNECT_DATA = + (SERVICE_NAME = vomsdb2.cr.cnaf.infn.it) + ) + ) + +COLLECTSRV = +(DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = atlas-cluster.cr.cnaf.infn.it)(PORT = 1521)) + (CONNECT_DATA = + (SERVER = DEDICATED) + (SERVICE_NAME = collectsrv.cr.cnaf.infn.it) + (FAILOVER_MODE = + (TYPE = SELECT)(METHOD = BASIC)(RETRIES = 180)(DELAY = 5) + ) + ) + ) diff --git a/docker/voms-admin-server/dev/centos7/setup/upgrade-db.sh b/docker/voms-admin-server/dev/centos7/setup/upgrade-db.sh new file mode 100644 index 00000000..587ec0d1 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/upgrade-db.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -ex + +VO_NAME_PREFIX=${VOMS_VO_NAME_PREFIX:-"test"} +VO_COUNT=${VOMS_VO_COUNT:-2} + +upgrade_db() { + VO_NAME=${VO_NAME_PREFIX}_$1 + if [[ -n "$VOMS_UPGRADE_DB" ]]; then + voms-db-util upgrade --vo ${VO_NAME} + fi +} + +for i in $(seq 0 ${VO_COUNT}); do + upgrade_db $i +done diff --git a/docker/voms-admin-server/push-image.sh b/docker/voms-admin-server/push-image.sh deleted file mode 100755 index bea534b0..00000000 --- a/docker/voms-admin-server/push-image.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -set -ex - -VOMS_ADMIN_SERVER_IMAGE=${VOMS_ADMIN_SERVER_IMAGE:-"italiangrid/voms-admin-server"} - -# The current script directory -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd ${DIR} - -if [ -z ${DOCKER_REGISTRY_HOST} ]; then - docker push ${VOMS_ADMIN_SERVER_IMAGE} -else - docker tag ${VOMS_ADMIN_SERVER_IMAGE} ${DOCKER_REGISTRY_HOST}/${VOMS_ADMIN_SERVER_IMAGE} - docker push ${DOCKER_REGISTRY_HOST}/${VOMS_ADMIN_SERVER_IMAGE} -fi From 66f7e4805584a475d353bd860fd4925fc308db45 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 4 Mar 2020 18:13:08 +0100 Subject: [PATCH 42/63] New HR plugin integrated with registration flow And various fixes --- compose/assets/hr/application.yml | 15 + compose/assets/hr/fixture/institutes.csv | 4 + compose/assets/hr/fixture/participations.csv | 4 + compose/assets/hr/fixture/vo_persons.csv | 4 + compose/assets/voms-admin/hr/hr.properties | 4 + compose/docker-compose.yml | 13 +- .../dev/centos7/setup/hr.template | 2 + .../dev/centos7/setup/run.sh | 9 + pom.xml | 6 + voms-admin-server/pom.xml | 8 +- .../security/voms/admin/core/VOMSService.java | 216 +++++++------- .../integration/cern/HrDbConfigurator.java | 71 +++-- .../integration/cern/HrDbExchangeError.java | 18 ++ .../cern/HrDbRequestValidator.java | 2 +- .../integration/cern/HrDefaultHandler.java | 4 +- .../cern/HttpClientHrDbApiService.java | 14 +- .../admin/integration/cern/dto/ErrorDTO.java | 6 +- .../integration/cern/dto/VOPersonDTO.java | 4 +- .../register/hr/HrRegisterActionSupport.java | 34 +++ .../register/hr/ResolveHrIdAction.java | 158 ++++++++++ .../view/actions/register/hr/StartAction.java | 35 +++ .../register/hr/SubmitRequestAction.java | 281 ++++++++++++++++++ .../user/SavePersonalInformationAction.java | 7 + .../WEB-INF/p/register/hr/registration.jsp | 43 +++ .../WEB-INF/p/register/hr/registration2.jsp | 90 ++++++ .../WEB-INF/p/register/hr/searchResults.jsp | 77 +++++ .../main/webapp/WEB-INF/p/user/userDetail.jsp | 2 +- .../src/main/webapp/WEB-INF/tiles.xml | 4 + .../hr/HrDbRequestValidatorTest.java | 6 +- .../java/integration/hr/HrDbTestSupport.java | 3 +- .../hr/HttpClientIntegrationTest.java | 70 +++-- .../test/resources/cern/json/voPerson1.json | 13 +- 32 files changed, 1041 insertions(+), 186 deletions(-) create mode 100644 compose/assets/hr/application.yml create mode 100644 compose/assets/hr/fixture/institutes.csv create mode 100644 compose/assets/hr/fixture/participations.csv create mode 100644 compose/assets/hr/fixture/vo_persons.csv create mode 100644 compose/assets/voms-admin/hr/hr.properties create mode 100644 docker/voms-admin-server/dev/centos7/setup/hr.template create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/StartAction.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/SubmitRequestAction.java create mode 100644 voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration.jsp create mode 100644 voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration2.jsp create mode 100644 voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/searchResults.jsp diff --git a/compose/assets/hr/application.yml b/compose/assets/hr/application.yml new file mode 100644 index 00000000..f3195052 --- /dev/null +++ b/compose/assets/hr/application.yml @@ -0,0 +1,15 @@ +server: + port: 9999 + +spring: + profiles: + include: + - fixture + +service: + api-user: + username: api-user + password: pwd + metrics-user: + username: metrics + password: pwd diff --git a/compose/assets/hr/fixture/institutes.csv b/compose/assets/hr/fixture/institutes.csv new file mode 100644 index 00000000..5377f33f --- /dev/null +++ b/compose/assets/hr/fixture/institutes.csv @@ -0,0 +1,4 @@ +id|longname|town|country +000000|Institute 0|Some place 0|IT| +000001|Apple Records|3 Abbey Road |GB| +000002|Sitcky Fingers|1 Ruby Tuesday Rd.|GB| diff --git a/compose/assets/hr/fixture/participations.csv b/compose/assets/hr/fixture/participations.csv new file mode 100644 index 00000000..7382545e --- /dev/null +++ b/compose/assets/hr/fixture/participations.csv @@ -0,0 +1,4 @@ +experiment|institute|person_id|start_date|end_date +TEST|000000|1|01-FEB-08| +TEST|000002|2|01-FEB-08| +TEST|000001|3|01-FEB-08| diff --git a/compose/assets/hr/fixture/vo_persons.csv b/compose/assets/hr/fixture/vo_persons.csv new file mode 100644 index 00000000..8b6d813d --- /dev/null +++ b/compose/assets/hr/fixture/vo_persons.csv @@ -0,0 +1,4 @@ +person_id|first_name|name|email|physical_email|institute +1|ANDREA|CECCANTI|ANDREA.CECCANTI@cnaf.infn.it|ACECCANT@cern.ch|000000 +2|KEITH|RICHARDS|keith@example.com|keith@cern.ch|000002 +3|PAUL|MC CARTNEY|paul@example.com|paul@cern.ch|000001 diff --git a/compose/assets/voms-admin/hr/hr.properties b/compose/assets/voms-admin/hr/hr.properties new file mode 100644 index 00000000..e2ce06ba --- /dev/null +++ b/compose/assets/voms-admin/hr/hr.properties @@ -0,0 +1,4 @@ +experiment=test +api.endpoint=http://hr:9999 +api.username=api-user +api.password=pwd diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index b0d31fd2..4eeef922 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -28,6 +28,16 @@ services: MYSQL_PASSWORD: pwd MYSQL_DATABASE: voms_test + hr: + image: indigoiam/cern-hr-db-api:latest + volumes: + - ./assets/hr/application.yml:/hr/application.yml:ro + - ./assets/hr/fixture/:/hr/src/test/resources/db/csv:ro + ports: + - "9999:9999" + environment: + TZ: UTC + adminserver: image: italiangrid/voms-admin-server-dev-centos7:latest domainname: local.io @@ -41,8 +51,9 @@ services: - ..:/code:ro - ~/git/orgdb-fake-users/:/orgdb-fake-users:ro - ~/git/voms-migrate:/migrate:ro - - ~/orgdb:/orgdb:ro - ~/oracle:/oracle-rpm:ro + - ./assets/voms-admin/hr:/hr:ro + # - ~/orgdb:/orgdb:ro ports: - "1044:1044" diff --git a/docker/voms-admin-server/dev/centos7/setup/hr.template b/docker/voms-admin-server/dev/centos7/setup/hr.template new file mode 100644 index 00000000..e15d0521 --- /dev/null +++ b/docker/voms-admin-server/dev/centos7/setup/hr.template @@ -0,0 +1,2 @@ +voms.external-validators = orgdb +voms.ext.orgdb.configClass = org.glite.security.voms.admin.integration.cern.HrDbConfigurator diff --git a/docker/voms-admin-server/dev/centos7/setup/run.sh b/docker/voms-admin-server/dev/centos7/setup/run.sh index d1c95a2d..eb02892e 100755 --- a/docker/voms-admin-server/dev/centos7/setup/run.sh +++ b/docker/voms-admin-server/dev/centos7/setup/run.sh @@ -135,6 +135,15 @@ if [ -e "/orgdb/orgdb.properties" ]; then cat ${SCRIPTS_PREFIX}/orgdb.template >> /etc/voms-admin/test_0/service.properties fi +if [ -e "/hr/hr.properties" ]; then + cp /hr/hr.properties /etc/voms-admin/test_0/hr.properties + chown voms:voms /etc/voms-admin/test_0/hr.properties + + # Just a newline + echo >> /etc/voms-admin/test_0/service.properties + cat ${SCRIPTS_PREFIX}/hr.template >> /etc/voms-admin/test_0/service.properties +fi + # Deploy test vos for i in $(seq 0 ${VO_COUNT}); do VO_NAME=${VO_NAME_PREFIX}_$i diff --git a/pom.xml b/pom.xml index fd72ead9..f0461442 100644 --- a/pom.xml +++ b/pom.xml @@ -128,6 +128,12 @@ ${jetty.version} + + org.eclipse.jetty + jetty-client + ${jetty.version} + + org.italiangrid https-utils diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 1f3ef2bd..eea676ed 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -94,7 +94,8 @@ WEB-INF/classes/logback*.xml, WEB-INF/lib/javax*.jar, - WEB-INF/lib/jetty-*.jar, + WEB-INF/lib/jetty-all-server*.jar, + WEB-INF/lib/jetty-jsp-*.jar, WEB-INF/lib/bcmail-*.jar, WEB-INF/lib/bcprov-*.jar, WEB-INF/lib/canl-*.jar, @@ -269,6 +270,11 @@ org.eclipse.jetty jetty-jsp + + + org.eclipse.jetty + jetty-client + javax.mail diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java index d72f255f..582de3eb 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java @@ -56,6 +56,7 @@ import org.glite.security.voms.admin.event.permission_cache.MembershipEventsCleanPermissionCacheListener; import org.glite.security.voms.admin.event.permission_cache.UserEventsCleanPermissionCacheListener; import org.glite.security.voms.admin.integration.PluginManager; +import org.glite.security.voms.admin.integration.cern.HrDbConfigurator; import org.glite.security.voms.admin.integration.orgdb.OrgDBConfigurator; import org.glite.security.voms.admin.integration.orgdb.servlet.OrgDbHibernateSessionFilter; import org.glite.security.voms.admin.notification.NotificationServiceFactory; @@ -96,9 +97,7 @@ public final class VOMSService { protected static void checkDatabaseVersion() { - final String detectedDbVersion = VOMSVersionDAO.instance() - .getVersion() - .getAdminVersion(); + final String detectedDbVersion = VOMSVersionDAO.instance().getVersion().getAdminVersion(); int detectedDbVersionInt = -1; @@ -106,10 +105,10 @@ protected static void checkDatabaseVersion() { detectedDbVersionInt = Math.abs(Integer.parseInt(detectedDbVersion)); } catch (NumberFormatException ex) { String msg = String.format( - "VOMS DATABASE SCHEMA ERROR: incompatible database. Found '%s' while expecting '%s'." - + " Please upgrade the database for this installation using 'voms-db-util upgrade'" - + " command.", - detectedDbVersion, SchemaVersion.VOMS_ADMIN_DB_VERSION); + "VOMS DATABASE SCHEMA ERROR: incompatible database. Found '%s' while expecting '%s'." + + " Please upgrade the database for this installation using 'voms-db-util upgrade'" + + " command.", + detectedDbVersion, SchemaVersion.VOMS_ADMIN_DB_VERSION); LOG.error(msg); throw new VOMSFatalException(msg); @@ -117,10 +116,10 @@ protected static void checkDatabaseVersion() { if (detectedDbVersionInt < SchemaVersion.VOMS_ADMIN_DB_VERSION_INT) { String msg = String.format( - "VOMS DATABASE SCHEMA ERROR: incompatible database. Found '%s' while expecting '%s'." - + " Please upgrade the database for this installation using 'voms-db-util upgrade'" - + " command.", - detectedDbVersion, SchemaVersion.VOMS_ADMIN_DB_VERSION); + "VOMS DATABASE SCHEMA ERROR: incompatible database. Found '%s' while expecting '%s'." + + " Please upgrade the database for this installation using 'voms-db-util upgrade'" + + " command.", + detectedDbVersion, SchemaVersion.VOMS_ADMIN_DB_VERSION); LOG.error(msg); throw new VOMSFatalException(msg); @@ -136,10 +135,10 @@ protected static void configureVelocity() { p.put("resource.loader", "cpath"); p.put("cpath.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); p.put("runtime.log.logsystem.class", - "org.glite.security.voms.admin.util.velocity.VelocityLogger"); + "org.glite.security.voms.admin.util.velocity.VelocityLogger"); Velocity.init(p); LOG.debug("Velocity setup ok!"); @@ -185,47 +184,46 @@ protected static void startBackgroundTasks() { DISABLE_BACKGROUND_TASK_PROPERTY); return; } - - + + VOMSConfiguration conf = VOMSConfiguration.instance(); List aupReminders = conf.getAUPReminderIntervals(); es.startBackgroundTask( - new SignAUPReminderCheckTask(DAOFactory.instance(), - EventManager.instance(), SystemTimeProvider.INSTANCE, aupReminders, - TimeUnit.DAYS), - VOMSConfigurationConstants.MEMBERSHIP_CHECK_PERIOD, 300L); - + new SignAUPReminderCheckTask(DAOFactory.instance(), EventManager.instance(), + SystemTimeProvider.INSTANCE, aupReminders, TimeUnit.DAYS), + VOMSConfigurationConstants.MEMBERSHIP_CHECK_PERIOD, 300L); + es.startBackgroundTask( - new CancelSignAUPTasksForExpiredUsersTask(DAOFactory.instance(), - EventManager.instance()), - VOMSConfigurationConstants.MEMBERSHIP_CHECK_PERIOD, 300L); - + new CancelSignAUPTasksForExpiredUsersTask(DAOFactory.instance(), EventManager.instance()), + VOMSConfigurationConstants.MEMBERSHIP_CHECK_PERIOD, 300L); + es.startBackgroundTask(new UpdateCATask(), - VOMSConfigurationConstants.TRUST_ANCHORS_REFRESH_PERIOD); + VOMSConfigurationConstants.TRUST_ANCHORS_REFRESH_PERIOD); es.startBackgroundTask(new TaskStatusUpdater(), 30L); - + es.startBackgroundTask( - new ExpiredRequestsPurgerTask(DAOFactory.instance(), - EventManager.instance()), - VOMSConfigurationConstants.VO_MEMBERSHIP_EXPIRED_REQ_PURGER_PERIOD, 300L); + new ExpiredRequestsPurgerTask(DAOFactory.instance(), EventManager.instance()), + VOMSConfigurationConstants.VO_MEMBERSHIP_EXPIRED_REQ_PURGER_PERIOD, 300L); es.startBackgroundTask(new UserStatsTask(), - VOMSConfigurationConstants.MONITORING_USER_STATS_UPDATE_PERIOD, - UserStatsTask.DEFAULT_PERIOD_IN_SECONDS); - + VOMSConfigurationConstants.MONITORING_USER_STATS_UPDATE_PERIOD, + UserStatsTask.DEFAULT_PERIOD_IN_SECONDS); + es.scheduleAtFixedRate(new PermissionCacheStatsLogger(true), 1, 60, TimeUnit.SECONDS); - - ExpiredUserCleanupTask userCleanupTask = new ExpiredUserCleanupTask(new DefaultCleanupUserLookupStrategy(conf)); - - es.startBackgroundTask(userCleanupTask, EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD, TimeUnit.HOURS.toSeconds(4)); - + + ExpiredUserCleanupTask userCleanupTask = + new ExpiredUserCleanupTask(new DefaultCleanupUserLookupStrategy(conf)); + + es.startBackgroundTask(userCleanupTask, EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD, + TimeUnit.HOURS.toSeconds(4)); + } protected static void startNotificationService() { - + if (System.getProperty(DISABLE_BACKGROUND_TASK_PROPERTY) != null) { LOG.warn("Background tasks disabled, as requested by system property {}", DISABLE_BACKGROUND_TASK_PROPERTY); @@ -237,11 +235,9 @@ protected static void startNotificationService() { PersistentNotificationService ns = PersistentNotificationService.INSTANCE; - ns.setNotificationSettings( - VOMSNotificationSettings.fromVOMSConfiguration()); + ns.setNotificationSettings(VOMSNotificationSettings.fromVOMSConfiguration()); - ns.setDao(DAOFactory.instance() - .getNotificationDAO()); + ns.setDao(DAOFactory.instance().getNotificationDAO()); ns.start(); } else { @@ -265,23 +261,21 @@ protected static void bootstrapAttributeAuthorityServices() { LOG.error("Error initializing OpenSAML:" + e.getMessage(), e); LOG.info("SAML endpoint will not be activated."); - conf.setProperty( - VOMSConfigurationConstants.VOMS_AA_SAML_ACTIVATE_ENDPOINT, false); + conf.setProperty(VOMSConfigurationConstants.VOMS_AA_SAML_ACTIVATE_ENDPOINT, false); } - boolean x509AcEndpointEnabled = conf.getBoolean( - VOMSConfigurationConstants.VOMS_AA_X509_ACTIVATE_ENDPOINT, false); + boolean x509AcEndpointEnabled = + conf.getBoolean(VOMSConfigurationConstants.VOMS_AA_X509_ACTIVATE_ENDPOINT, false); if (x509AcEndpointEnabled) { LOG.info("Bootstrapping VOMS X.509 attribute authority."); - ACGeneratorFactory.newACGenerator() - .configure(conf.getServiceCredential()); + ACGeneratorFactory.newACGenerator().configure(conf.getServiceCredential()); VOMSExecutorService es = VOMSExecutorService.instance(); es.scheduleAtFixedRate(new PrintX509AAStatsTask(), - PrintX509AAStatsTask.DEFAULT_PERIOD_IN_SECS, - PrintX509AAStatsTask.DEFAULT_PERIOD_IN_SECS, TimeUnit.SECONDS); + PrintX509AAStatsTask.DEFAULT_PERIOD_IN_SECS, PrintX509AAStatsTask.DEFAULT_PERIOD_IN_SECS, + TimeUnit.SECONDS); } else { LOG.info("X.509 attribute authority is disabled."); @@ -299,24 +293,24 @@ protected static void configureLogging(ServletContext ctxt) { File f = new File(loggingConf); if (!f.exists()) - throw new VOMSFatalException(String.format( - "Logging configuration " + "not found at path '%s'", loggingConf)); + throw new VOMSFatalException( + String.format("Logging configuration " + "not found at path '%s'", loggingConf)); if (!f.canRead()) - throw new VOMSFatalException(String - .format("Logging configuration " + "is not readable: %s", loggingConf)); + throw new VOMSFatalException( + String.format("Logging configuration " + "is not readable: %s", loggingConf)); LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); lc.setName(vo); - + JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); - + lc.reset(); - + // We leave this here to avoid runtime errors for people that - // update the service, but not the logging configuration + // update the service, but not the logging configuration // FIXME: to be removed at some point lc.putProperty(VOMSConfigurationConstants.VO_NAME, vo); @@ -341,64 +335,58 @@ public static void bootstrapPersistence(VOMSConfiguration configuration) { private static void initializeDnValidator() { - VOMSAdminDnValidator.INSTANCE.initialize("/etc/grid-security/certificates", - true); + VOMSAdminDnValidator.INSTANCE.initialize("/etc/grid-security/certificates", true); } - private static void configureOrgDbHibernateSessionFitler(ServletContext ctxt){ - if (!VOMSConfiguration.instance().getRegistrationType().equals( - OrgDBConfigurator.ORGDB_REGISTRATION_TYPE)){ + private static void configureOrgDbHibernateSessionFitler(ServletContext ctxt) { + if (!VOMSConfiguration.instance() + .getRegistrationType() + .equals(OrgDBConfigurator.ORGDB_REGISTRATION_TYPE)) { return; } - - FilterRegistration.Dynamic fr = ctxt.addFilter("orgdb-hibernate-session-filter", - OrgDbHibernateSessionFilter.class); - + + FilterRegistration.Dynamic fr = + ctxt.addFilter("orgdb-hibernate-session-filter", OrgDbHibernateSessionFilter.class); + fr.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "*"); - + } - - - private static void setupGlobalApplicationObjects(ServletContext ctxt){ - + + + private static void setupGlobalApplicationObjects(ServletContext ctxt) { + AUP aup = DAOFactory.instance().getAUPDAO().getVOAUP(); - ctxt.setAttribute( - "registrationEnabled", - VOMSConfiguration.instance().getBoolean( - VOMSConfigurationConstants.REGISTRATION_SERVICE_ENABLED, true)); - - ctxt.setAttribute( - "readOnlyPI", - VOMSConfiguration.instance() - .getBoolean( - VOMSConfigurationConstants.VOMS_INTERNAL_RO_PERSONAL_INFORMATION, - false)); - - ctxt.setAttribute( - "readOnlyMembershipExpiration", - VOMSConfiguration.instance().getBoolean( - VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, - false)); - - ctxt.setAttribute( - "disableMembershipEndTime", - VOMSConfiguration.instance().getBoolean( - VOMSConfigurationConstants.DISABLE_MEMBERSHIP_END_TIME, false)); + ctxt.setAttribute("registrationEnabled", VOMSConfiguration.instance() + .getBoolean(VOMSConfigurationConstants.REGISTRATION_SERVICE_ENABLED, true)); + + ctxt.setAttribute("readOnlyPI", VOMSConfiguration.instance() + .getBoolean(VOMSConfigurationConstants.VOMS_INTERNAL_RO_PERSONAL_INFORMATION, false)); + + ctxt.setAttribute("readOnlyMembershipExpiration", VOMSConfiguration.instance() + .getBoolean(VOMSConfigurationConstants.VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, false)); + + ctxt.setAttribute("disableMembershipEndTime", VOMSConfiguration.instance() + .getBoolean(VOMSConfigurationConstants.DISABLE_MEMBERSHIP_END_TIME, false)); ctxt.setAttribute("defaultAUP", aup); - + ctxt.setAttribute("orgdbEnabled", - VOMSConfiguration.instance().getRegistrationType().equals( - OrgDBConfigurator.ORGDB_REGISTRATION_TYPE)); - + VOMSConfiguration.instance() + .getRegistrationType() + .equals(OrgDBConfigurator.ORGDB_REGISTRATION_TYPE)); + + ctxt.setAttribute("hrEnabled", + VOMSConfiguration.instance() + .getRegistrationType() + .equals(HrDbConfigurator.HR_DB_REGISTRATION_TYPE)); + } - - + + public static void start(ServletContext ctxt) { - Thread - .setDefaultUncaughtExceptionHandler(new ThreadUncaughtExceptionHandler()); + Thread.setDefaultUncaughtExceptionHandler(new ThreadUncaughtExceptionHandler()); configureLogging(ctxt); @@ -433,34 +421,31 @@ public static void start(ServletContext ctxt) { bootstrapAttributeAuthorityServices(); - PluginManager.instance() - .configurePlugins(); + PluginManager.instance().configurePlugins(); - ValidationManager.instance() - .startMembershipChecker(); + ValidationManager.instance().startMembershipChecker(); initializeDnValidator(); configureOrgDbHibernateSessionFitler(ctxt); - + setupGlobalApplicationObjects(ctxt); - + LOG.info("VOMS-Admin started succesfully."); } private static void configureCertificateLookupPolicy(VOMSConfiguration conf) { - boolean skipCaCheck = conf - .getBoolean(VOMSConfigurationConstants.SKIP_CA_CHECK, false); + boolean skipCaCheck = conf.getBoolean(VOMSConfigurationConstants.SKIP_CA_CHECK, false); if (skipCaCheck) { LOG.info( - "CertificateLookupPolicy: VOMS Users, certificates and administrators will be looked up by certificate subject ({} == true)", - VOMSConfigurationConstants.SKIP_CA_CHECK); + "CertificateLookupPolicy: VOMS Users, certificates and administrators will be looked up by certificate subject ({} == true)", + VOMSConfigurationConstants.SKIP_CA_CHECK); } else { LOG.info( - "CertficateLookupPolicy: VOMS Users, certificates and administrators will be looked up by certificate subject AND issuer ({} == false)", - VOMSConfigurationConstants.SKIP_CA_CHECK); + "CertficateLookupPolicy: VOMS Users, certificates and administrators will be looked up by certificate subject AND issuer ({} == false)", + VOMSConfigurationConstants.SKIP_CA_CHECK); } LookupPolicyProvider.initialize(skipCaCheck); @@ -479,8 +464,7 @@ public static void stop() { VOMSExecutorService.shutdown(); - NotificationServiceFactory.getNotificationService() - .shutdownNow(); + NotificationServiceFactory.getNotificationService().shutdownNow(); HibernateFactory.shutdown(); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java index 7a3003be..42cff7e5 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java @@ -39,31 +39,34 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class HrDbConfigurator extends AbstractPluginConfigurator { +public class HrDbConfigurator extends AbstractPluginConfigurator + implements HrDbRequestValidatorFactory { public static final Logger LOG = LoggerFactory.getLogger(HrDbConfigurator.class); - public static final String DEFAULT_CONFIG_FILE_NAME = "orgdb.properties"; + public static final String DEFAULT_CONFIG_FILE_NAME = "hr.properties"; public static final String HR_DB_EXPERIMENT_NAME_PROPERTY = "experiment_name"; public static final String HR_DB_MEMBERSHIP_CHECK_PERIOD_IN_SECONDS = "membership_check.period"; - public static final String HR_DB_REGISTRATION_TYPE = "orgdb"; + public static final String HR_DB_REGISTRATION_TYPE = "hr"; - Clock clock; - VOMSExecutorService executorService; - VOMSUserDAO userDao; - ValidationManager validationManager; - HrDbApiServiceFactory apiServiceFactory; - HrDbSyncTaskFactory syncTaskFactory; - HrDbRequestValidatorFactory requestValidatorFactory; - HrDbProperties hrConfig; + private Clock clock; + private VOMSExecutorService executorService; + private VOMSUserDAO userDao; + private ValidationManager validationManager; + private HrDbApiServiceFactory apiServiceFactory; + private HrDbSyncTaskFactory syncTaskFactory; + private HrDbRequestValidatorFactory requestValidatorFactory; + private HrDbProperties hrConfig; + + private HrDbApiService apiService; public HrDbConfigurator(VOMSConfiguration config) { super(config); } - private HrDbProperties loadHrDBDatabaseProperties() throws VOMSPluginConfigurationException { + private HrDbProperties loadHrDBProperties() throws VOMSPluginConfigurationException { String defaultConfigFilePath = getVomsConfigurationDirectoryPath() + "/" + DEFAULT_CONFIG_FILE_NAME; @@ -81,7 +84,7 @@ private HrDbProperties loadHrDBDatabaseProperties() throws VOMSPluginConfigurati throw new VOMSPluginConfigurationException(errorMessage, e); } - + return HrDbProperties.fromProperties(hrDbProps); } @@ -112,7 +115,15 @@ void initDependencies() throws VOMSPluginConfigurationException { } if (isNull(hrConfig)) { - hrConfig = loadHrDBDatabaseProperties(); + hrConfig = loadHrDBProperties(); + } + + if (isNull(requestValidatorFactory)) { + requestValidatorFactory = this; + } + + if (isNull(syncTaskFactory)) { + syncTaskFactory = new DefaultHrDbSyncTaskFactory(clock, validationManager); } } @@ -158,22 +169,21 @@ public void configure() throws VOMSPluginConfigurationException { VOMSConfiguration config = getVomsConfig(); config.setRegistrationType(HR_DB_REGISTRATION_TYPE); - config.setProperty(VOMS_INTERNAL_RO_PERSONAL_INFORMATION, - Boolean.TRUE); - config.setProperty(VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, - Boolean.TRUE); + config.setProperty(VOMS_INTERNAL_RO_PERSONAL_INFORMATION, Boolean.TRUE); + config.setProperty(VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE, Boolean.TRUE); config.setProperty(PI_REQUIRED_FIELDS, ""); - - HrDbApiService api = apiServiceFactory.newHrDbApiService(hrConfig); - validationManager - .setRequestValidationContext(requestValidatorFactory.newHrDbRequestValidator(hrConfig, api)); + apiService = apiServiceFactory.newHrDbApiService(hrConfig); + + validationManager.setRequestValidationContext( + requestValidatorFactory.newHrDbRequestValidator(hrConfig, apiService)); LOG.info("HR DB request validator registered succesfully"); if (hrConfig.getMembesrshipCheck().isEnabled()) { - scheduleSyncTask(hrConfig, syncTaskFactory.buildSyncTask(hrConfig, api, userDao, config)); + scheduleSyncTask(hrConfig, + syncTaskFactory.buildSyncTask(hrConfig, apiService, userDao, config)); } else { LOG.info("HR DB sync task DISABLED as requested by configuration"); } @@ -213,4 +223,19 @@ public void setClock(Clock clock) { public void setHrConfig(HrDbProperties hrConfig) { this.hrConfig = hrConfig; } + + @Override + public HrDbRequestValidator newHrDbRequestValidator(HrDbProperties properties, + HrDbApiService api) { + + return new HrDbRequestValidator(clock, properties, api); + } + + public HrDbApiService getApiService() { + return apiService; + } + + public HrDbProperties getHrConfig() { + return hrConfig; + } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java new file mode 100644 index 00000000..063b10e5 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java @@ -0,0 +1,18 @@ +package org.glite.security.voms.admin.integration.cern; + +public class HrDbExchangeError extends HrDbError { + + private static final long serialVersionUID = 1L; + + private final int responseStatus; + + public HrDbExchangeError(int responseStatus, String responseMessage) { + super(responseMessage); + this.responseStatus = responseStatus; + } + + public int getResponseStatus() { + return responseStatus; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java index abdbf063..1b95706e 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbRequestValidator.java @@ -78,7 +78,7 @@ protected void propertyEqualsIgnoreCase(String value1, String value2, String pro RequestValidationResult validateRequestData(NewVOMembershipRequest request, VOPersonDTO person) { Optional participation = person - .findValidParticipationsForExperiment(clock.instant(), properties.getExperimentName()); + .findValidParticipationForExperiment(clock.instant(), properties.getExperimentName()); if (participation.isPresent()) { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java index 64788e02..783be33a 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java @@ -86,7 +86,7 @@ public void synchronizeMembershipInformation(VOMSUser user, VOPersonDTO voPerson user.setEmailAddress(orgDbEmailAddress.toLowerCase()); Optional participation = - voPerson.findValidParticipationsForExperiment(now, config.getExperimentName()); + voPerson.findValidParticipationForExperiment(now, config.getExperimentName()); if (participation.isPresent()) { user.setEndTime(participation.get().getEndDate()); @@ -94,6 +94,8 @@ public void synchronizeMembershipInformation(VOMSUser user, VOPersonDTO voPerson } else { handleExpiredParticipation(user, voPerson); } + + LOG.info("Synced user {} against record {}", user.getShortName(), voPerson.getId()); } @Override diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java index 7a68e027..e1129005 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java @@ -30,6 +30,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.util.ajax.JSON; +import org.glite.security.voms.admin.integration.cern.dto.ErrorDTO; import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; import org.glite.security.voms.admin.persistence.model.VOMSUser; import org.slf4j.Logger; @@ -107,13 +108,12 @@ protected void handleExchange(ContentExchange ce) { if (HttpExchange.STATUS_COMPLETED == exchangeStatus) { if (ce.getResponseStatus() != 200) { - - final String errorMsg = - String.format("HR Db Api Http request %s yelded response status: %d ", - ce.getRequestURI(), ce.getResponseStatus()); - throw new HrDbError(errorMsg); + + @SuppressWarnings("unchecked") + ErrorDTO error = ErrorDTO.fromJsonMap((Map) JSON.parse(ce.getResponseContent())); + throw new HrDbExchangeError(ce.getResponseStatus(), error.getErrorMessage()); } - } else if (HttpExchange.STATUS_EXPIRED == exchangeStatus){ + } else if (HttpExchange.STATUS_EXPIRED == exchangeStatus) { throw new HrDbError("Error contacting the HR DB api: request timeout exceeded"); } else { throw new HrDbError("Error contacting the HR DB api"); @@ -189,7 +189,7 @@ public boolean hasValidExperimentParticipationByEmail(String email) { Instant now = clock.instant(); return getVoPersonRecordByEmail(email) - .map(p -> p.findValidParticipationsForExperiment(now, experimentName)) + .filter(p -> p.findValidParticipationForExperiment(now, experimentName).isPresent()) .isPresent(); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java index b72c9be3..aa6c8508 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/ErrorDTO.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.integration.cern.dto; +import java.util.Map; + public class ErrorDTO { final String error; @@ -45,5 +47,7 @@ public static ErrorDTO newError(String error) { return new ErrorDTO(error); } - + public static ErrorDTO fromJsonMap(Map json) { + return newError((String) json.get("error"), (String) json.get("errorMessage")); + } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java index 9bf01cbf..cb7128ad 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/dto/VOPersonDTO.java @@ -181,11 +181,11 @@ public void setParticipations(Set participations) { this.participations = participations; } - public Optional findValidParticipationsForExperiment(Instant now, + public Optional findValidParticipationForExperiment(Instant now, String experimentName) { return getParticipations().stream() - .filter(p -> p.getExperiment().equals(experimentName) && p.isValidAtInstant(now)) + .filter(p -> p.getExperiment().equalsIgnoreCase(experimentName) && p.isValidAtInstant(now)) .findFirst(); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java new file mode 100644 index 00000000..aed073ce --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java @@ -0,0 +1,34 @@ +package org.glite.security.voms.admin.view.actions.register.hr; + +import static java.util.Objects.isNull; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; +import org.glite.security.voms.admin.persistence.model.request.RequesterInfo; +import org.glite.security.voms.admin.view.actions.register.RegisterActionSupport; + +public class HrRegisterActionSupport extends RegisterActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private Map session; + + @Override + public void prepare() throws Exception { + super.prepare(); + requester = (RequesterInfo) session.get(ResolveHrIdAction.REQUESTER_INFO_KEY); + } + + @Override + public void validate() { + if (isNull(requester)) { + addActionError("Application information not found in session!"); + } + } + @Override + public void setSession(Map session) { + this.session = session; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java new file mode 100644 index 00000000..598fc7f8 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java @@ -0,0 +1,158 @@ +package org.glite.security.voms.admin.view.actions.register.hr; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; +import org.apache.struts2.interceptor.SessionAware; +import org.glite.security.voms.admin.core.VOMSServiceConstants; +import org.glite.security.voms.admin.integration.PluginManager; +import org.glite.security.voms.admin.integration.cern.HrDbApiService; +import org.glite.security.voms.admin.integration.cern.HrDbConfigurator; +import org.glite.security.voms.admin.integration.cern.HrDbError; +import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; +import org.glite.security.voms.admin.integration.cern.dto.VOPersonDTO; +import org.glite.security.voms.admin.operations.CurrentAdmin; +import org.glite.security.voms.admin.persistence.model.request.RequesterInfo; +import org.glite.security.voms.admin.view.actions.BaseAction; + +import com.google.common.collect.Lists; +import com.opensymphony.xwork2.ModelDriven; +import com.opensymphony.xwork2.Preparable; + +@Results({ + + @Result(name = BaseAction.SUCCESS, location = "searchResults.jsp"), + @Result(name = BaseAction.INPUT, location = "searchResults.jsp") + +}) +public class ResolveHrIdAction extends BaseAction + implements ModelDriven>, Preparable, SessionAware { + + public static final String VO_PERSON_KEY = "__voms.voPerson"; + public static final String REQUESTER_INFO_KEY = "__voms.requesterInfo"; + + + /** + * + */ + private static final long serialVersionUID = 1L; + + RequesterInfo requester; + + String emailAddress; + + List searchResults; + + String experimentName; + + Instant now; + + Map session; + + protected RequesterInfo requesterInfoFromCurrentAdmin() { + + RequesterInfo i = new RequesterInfo(); + CurrentAdmin admin = CurrentAdmin.instance(); + + i.setCertificateSubject(admin.getRealSubject()); + i.setCertificateIssuer(admin.getRealIssuer()); + i.setEmailAddress(admin.getRealEmailAddress()); + + return i; + + } + + public void prepare() throws Exception { + requester = requesterInfoFromCurrentAdmin(); + } + + public RequesterInfo getRequester() { + return requester; + } + + public void setRequester(RequesterInfo requester) { + this.requester = requester; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } + + public List getSearchResults() { + return searchResults; + } + + @Override + public String execute() throws Exception { + + searchResults = Lists.newArrayList(); + HrDbConfigurator hrPlugin = (HrDbConfigurator) PluginManager.instance() + .getConfiguredPlugin(HrDbConfigurator.class.getName()); + + experimentName = hrPlugin.getHrConfig().getExperimentName(); + now = Instant.now(); + + HrDbApiService apiService = hrPlugin.getApiService(); + try { + if (apiService.hasValidExperimentParticipationByEmail(emailAddress)) { + Optional voPerson = apiService.getVoPersonRecordByEmail(emailAddress); + + // Can't use functional approach otherwise old struts bytecode gets confused?? + if (voPerson.isPresent()) { + + VOPersonDTO p = voPerson.get(); + session.put(VO_PERSON_KEY, p); + searchResults.add(p); + requester.setName(p.getFirstName()); + requester.setSurname(p.getName()); + requester.setEmailAddress(emailAddress); + Optional pp = + p.findValidParticipationForExperiment(now, experimentName); + if (pp.isPresent()) { + requester.setInstitution(pp.get().getInstitute().getName()); + } else { + requester.setInstitution("N/A"); + } + + requester.addInfo(VOMSServiceConstants.ORGDB_ID_KEY, p.getId().toString()); + + session.put(REQUESTER_INFO_KEY, requester); + } + } else { + + addActionError( + String.format("No valid participation found for email '%s' in experiment '%s'", + emailAddress, hrPlugin.getHrConfig().getExperimentName())); + } + } catch (HrDbError e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } + + @Override + public List getModel() { + return searchResults; + } + + public String getExperimentName() { + return experimentName; + } + + public Instant getNow() { + return now; + } + + @Override + public void setSession(Map session) { + this.session = session; + } +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/StartAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/StartAction.java new file mode 100644 index 00000000..677eeb56 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/StartAction.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.view.actions.register.hr; + +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; +import org.glite.security.voms.admin.view.actions.BaseAction; + +@Results({ @Result(name = BaseAction.SUCCESS, location = "hrRegister") }) +public class StartAction extends HrRegisterActionSupport{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public String execute() throws Exception { + return SUCCESS; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/SubmitRequestAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/SubmitRequestAction.java new file mode 100644 index 00000000..f1c3c31e --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/SubmitRequestAction.java @@ -0,0 +1,281 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glite.security.voms.admin.view.actions.register.hr; + +import java.util.Calendar; +import java.util.Date; + +import org.apache.struts2.convention.annotation.InterceptorRef; +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.core.validation.RequestValidationResult; +import org.glite.security.voms.admin.core.validation.RequestValidationResult.Outcome; +import org.glite.security.voms.admin.core.validation.ValidationManager; +import org.glite.security.voms.admin.event.EventManager; +import org.glite.security.voms.admin.event.request.VOMembershipRequestSubmittedEvent; +import org.glite.security.voms.admin.persistence.dao.generic.DAOFactory; +import org.glite.security.voms.admin.util.URLBuilder; +import org.glite.security.voms.admin.view.actions.BaseAction; +import org.glite.security.voms.admin.view.actions.register.RegisterActionSupport; + +import com.opensymphony.xwork2.validator.annotations.EmailValidator; +import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; +import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator; +import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; +import com.opensymphony.xwork2.validator.annotations.ValidatorType; + +@Results({ + @Result(name = BaseAction.INPUT, location = "hrRegister"), + @Result(name = BaseAction.SUCCESS, location = "registerConfirmation"), + @Result(name = RegisterActionSupport.CONFIRMATION_NEEDED, + location = "registerConfirmation"), + @Result(name = RegisterActionSupport.REGISTRATION_DISABLED, + location = "registrationDisabled"), + @Result(name = RegisterActionSupport.PLUGIN_VALIDATION_ERROR, + location = "pluginValidationError") }) +@InterceptorRef(value = "authenticatedStack", params = { + "token.includeMethods", "execute" }) +public class SubmitRequestAction extends HrRegisterActionSupport { + + /** + * + */ + private static final long serialVersionUID = 1L; + + String name; + String surname; + + String institution; + String address; + + String phoneNumber; + + String emailAddress; + + String aupAccepted; + + String userMessage; + + RequestValidationResult validationResult; + + protected void populateRequestModel() { + + long requestLifetime = VOMSConfiguration.instance().getLong( + "voms.request.vo_membership.lifetime", 300); + + Date expirationDate = getFutureDate(new Date(), Calendar.SECOND, + (int) requestLifetime); + + requester.setName(name); + requester.setSurname(surname); + requester.setInstitution(institution); + requester.setAddress(address); + requester.setPhoneNumber(phoneNumber); + requester.setEmailAddress(emailAddress); + + request = DAOFactory.instance().getRequestDAO() + .createVOMembershipRequest(requester, expirationDate); + + request.setUserMessage(userMessage); + + } + + @Override + public String execute() throws Exception { + + if (!registrationEnabled()) + return REGISTRATION_DISABLED; + + String result = checkExistingPendingRequests(); + + if (result != null) { + return result; + } + + populateRequestModel(); + + // External plugin validation + validationResult = ValidationManager.instance().validateRequest(request); + if (!validationResult.getOutcome().equals(Outcome.SUCCESS)) { + + DAOFactory.instance().getRequestDAO().makeTransient(request); + addActionError(validationResult.getMessage()); + return PLUGIN_VALIDATION_ERROR; + } + + EventManager.instance().dispatch( + new VOMembershipRequestSubmittedEvent(request, URLBuilder + .buildRequestConfirmURL(getModel()), URLBuilder + .buildRequestCancelURL(getModel()))); + + return SUCCESS; + } + + /** + * @return the name + */ + public String getName() { + + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + + this.name = name; + } + + /** + * @return the surname + */ + public String getSurname() { + + return surname; + } + + /** + * @param surname + * the surname to set + */ + public void setSurname(String surname) { + + this.surname = surname; + } + + /** + * @return the institution + */ + @RequiredStringValidator(type = ValidatorType.FIELD, + message = "Please enter your institution.") + public String getInstitution() { + + return institution; + } + + /** + * @param institution + * the institution to set + */ + public void setInstitution(String institution) { + + this.institution = institution; + } + + /** + * @return the address + */ + @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", + message = "You entered invalid characters.") + public String getAddress() { + + return address; + } + + /** + * @param address + * the address to set + */ + public void setAddress(String address) { + + this.address = address; + } + + /** + * @return the phoneNumber + */ + @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", + message = "You entered invalid characters.") + public String getPhoneNumber() { + + return phoneNumber; + } + + /** + * @param phoneNumber + * the phoneNumber to set + */ + public void setPhoneNumber(String phoneNumber) { + + this.phoneNumber = phoneNumber; + } + + /** + * @return the emailAddress + */ + @RequiredStringValidator(type = ValidatorType.FIELD, + message = "Please enter your email address.") + @EmailValidator(type = ValidatorType.FIELD, + message = "Please enter a valid email address.") + public String getEmailAddress() { + + return emailAddress; + } + + /** + * @param emailAddress + * the emailAddress to set + */ + public void setEmailAddress(String emailAddress) { + + this.emailAddress = emailAddress; + } + + /** + * @return the aupAccepted + */ + @RequiredFieldValidator(type = ValidatorType.FIELD, + message = "You must sign the AUP.") + @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^true$", + message = "You must accept the terms of the AUP to proceed") + public String getAupAccepted() { + + return aupAccepted; + } + + /** + * @param aupAccepted + * the aupAccepted to set + */ + public void setAupAccepted(String aupAccepted) { + + this.aupAccepted = aupAccepted; + } + + @RegexFieldValidator(type = ValidatorType.FIELD, regex = "^[^<>&=;]*$", + message = "You entered invalid characters.") + public String getUserMessage() { + + return userMessage; + } + + public void setUserMessage(String userMessage) { + + this.userMessage = userMessage; + } + + /** + * @return the validationResult + */ + public RequestValidationResult getValidationResult() { + + return validationResult; + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java index 07c67696..5cee5169 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/user/SavePersonalInformationAction.java @@ -26,6 +26,7 @@ import org.glite.security.voms.admin.configuration.VOMSConfiguration; import org.glite.security.voms.admin.error.IllegalStateException; import org.glite.security.voms.admin.integration.PluginManager; +import org.glite.security.voms.admin.integration.cern.HrDbConfigurator; import org.glite.security.voms.admin.integration.orgdb.OrgDBConfigurator; import org.glite.security.voms.admin.integration.orgdb.strategies.OrgDBEmailValidationResult; import org.glite.security.voms.admin.operations.users.SaveUserPersonalInfoOperation; @@ -56,6 +57,12 @@ public class SavePersonalInformationAction extends UserActionSupport { private static final String[] ORGDB_VALIDATED_FIELDS = {"theAddress", "thePhoneNumber"}; + private boolean isHrPluginEnabled() { + return VOMSConfiguration.instance() + .getRegistrationType() + .equals(HrDbConfigurator.HR_DB_REGISTRATION_TYPE); + } + private boolean isOrgDBPluginEnabled() { return VOMSConfiguration.instance() diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration.jsp new file mode 100644 index 00000000..dad36592 --- /dev/null +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration.jsp @@ -0,0 +1,43 @@ +<%-- + + Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--%> +<%@include file="/WEB-INF/p/shared/taglibs.jsp"%> + +

    +Welcome to the registration page for the ${voName} +Virtual Organization! +

    + +

    +To apply for membership in this Virtual Organization, you must +be registered in the CERN Human Resource database and have your membership +there linked to the ${voName} experiment. +

    + +

    +The VO registration process requires that you know the email address linked +to your CERN Human Resource record. To find out your CERN Human Resource +record, use the +CERN Phonebook service before proceeding with the registration. +

    + +

    +Please enter the following information: +

    + + + diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration2.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration2.jsp new file mode 100644 index 00000000..528bae00 --- /dev/null +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/registration2.jsp @@ -0,0 +1,90 @@ +<%-- + + Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--%> +<%@include file="/WEB-INF/p/shared/taglibs.jsp"%> + +

    +Welcome to the registration page for the ${voName} VO. +

    + +

    +To access the VO resources, you must agree to the VO's Acceptable Usage Policy (AUP) rules. +
    +Please fill out all the fields in the form below and click on the submit +button at the bottom of the page. +

    +

    +After you submit this request, you will receive an email with instructions on how to proceed. +
    + +Your request will not be forwarded to the VO managers until you confirm that you have a valid email +address by following those instructions. +

    + +

    IMPORTANT:

    +

    +By submitting this information you agree that it may be distributed to and stored by +VO and site administrators. You also agree that action may be taken to confirm the information you provide +is correct, that it may be used for the purpose of controlling access to VO resources and that it may be +used to contact you in relation to this activity. +

    + + + + +

    Your certificate subject (DN):

    +
    + +
    +

    The CA that issued your certificate:

    +
    + +
    +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • +

      The VO Acceptable Usage Policy (AUP):

      + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
    \ No newline at end of file diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/searchResults.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/searchResults.jsp new file mode 100644 index 00000000..ccd6c06f --- /dev/null +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/register/hr/searchResults.jsp @@ -0,0 +1,77 @@ +<%-- + + Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--%> +<%@include file="/WEB-INF/p/shared/taglibs.jsp"%> +
    + +
      +
    • + +
    • + +
    +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + +
    CERN Person IDNameSurnameInstituteEmail addresses +
    + + + + + + + + +
    + +
    +
    + +
    +
    + + + +
    +
    +
    +
    \ No newline at end of file diff --git a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp index f10aae2f..e89ced2b 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp +++ b/voms-admin-server/src/main/webapp/WEB-INF/p/user/userDetail.jsp @@ -25,7 +25,7 @@
    ( ${id} ) - + diff --git a/voms-admin-server/src/main/webapp/WEB-INF/tiles.xml b/voms-admin-server/src/main/webapp/WEB-INF/tiles.xml index 17f92988..1747a711 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/tiles.xml +++ b/voms-admin-server/src/main/webapp/WEB-INF/tiles.xml @@ -180,6 +180,10 @@ + + + + diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java index d90fa6af..df681eb0 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbRequestValidatorTest.java @@ -92,7 +92,7 @@ public void testNoValidParticipation() { when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); when(person.getFirstName()).thenReturn("TEST"); when(person.getName()).thenReturn("USER"); - when(person.findValidParticipationsForExperiment(any(), anyString())) + when(person.findValidParticipationForExperiment(any(), anyString())) .thenReturn(empty()); @@ -113,7 +113,7 @@ public void testDataMismatch() { when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); when(person.getFirstName()).thenReturn("TEST"); when(person.getName()).thenReturn("USER"); - when(person.findValidParticipationsForExperiment(any(), anyString())) + when(person.findValidParticipationForExperiment(any(), anyString())) .thenReturn(Optional.of(participation)); RequestValidationResult result = validator.validateRequest(request); @@ -133,7 +133,7 @@ public void testValidationSuccess() { when(person.getPhysicalEmail()).thenReturn("test@cern.ch"); when(person.getFirstName()).thenReturn("ADRIENNE"); when(person.getName()).thenReturn("LENKER"); - when(person.findValidParticipationsForExperiment(any(), anyString())) + when(person.findValidParticipationForExperiment(any(), anyString())) .thenReturn(Optional.of(participation)); RequestValidationResult result = validator.validateRequest(request); diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java b/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java index 0468142f..5e526e4f 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbTestSupport.java @@ -40,5 +40,6 @@ public class HrDbTestSupport { public static final String VO_PERSON_1_JSON_PATH = "src/test/resources/cern/json/voPerson1.json"; public static final String VO_PERSON_1_JSON = readFile(VO_PERSON_1_JSON_PATH); - + public static final String ERROR_404_JSON = "{\"error\":\"NOT_FOUND\", \"errorMessage\":\"404 - Not found\"}"; + public static final String ERROR_403_JSON = "{\"error\":\"FORBIDDEN\", \"errorMessage\":\"403 - Forbidden\"}"; } diff --git a/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java b/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java index 03542db7..3f947094 100644 --- a/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HttpClientIntegrationTest.java @@ -15,6 +15,7 @@ */ package integration.hr; +import static java.util.stream.Collectors.toList; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -27,11 +28,13 @@ import static org.mockserver.model.HttpResponse.response; import static utils.TestSocketUtils.findAvailableTcpPort; +import java.util.List; import java.util.Optional; import java.util.Random; import java.util.concurrent.TimeUnit; import org.glite.security.voms.admin.integration.cern.HrDbError; +import org.glite.security.voms.admin.integration.cern.HrDbExchangeError; import org.glite.security.voms.admin.integration.cern.HrDbProperties; import org.glite.security.voms.admin.integration.cern.HttpClientHrDbApiService; import org.glite.security.voms.admin.integration.cern.dto.ParticipationDTO; @@ -46,7 +49,7 @@ import org.mockserver.model.HttpError; import org.mockserver.model.HttpResponse; -public class HttpClientIntegrationTest extends HrDbTestSupport{ +public class HttpClientIntegrationTest extends HrDbTestSupport { private static int port; private static ClientAndServer mockServer; @@ -68,13 +71,14 @@ public static void stopMockServer() { @Before public void setup() { properties = new HrDbProperties(); - properties.setExperimentName("cms"); + properties.setExperimentName("atlas"); properties.getApi().setEndpoint("http://localhost:" + port); properties.getApi().setUsername("user"); properties.getApi().setPassword("password"); properties.getApi().setTimeoutInSeconds(1L); apiService = new HttpClientHrDbApiService(CLOCK, properties); + mockServer.reset(); } @After @@ -86,13 +90,13 @@ public void teardown() { @Test(expected = HrDbError.class) public void testVoPersonAuthNErrorHandling() { mockServer.when(request("/api/VOPersons/1").withMethod("GET"), once()) - .respond(HttpResponse.response().withStatusCode(403)); + .respond(HttpResponse.response().withStatusCode(403).withBody(ERROR_403_JSON)); try { apiService.getVoPersonRecord(1); - } catch (HrDbError e) { - + } catch (HrDbExchangeError e) { + assertThat(e.getMessage(), containsString("403")); mockServer.verify(request("/api/VOPersons/1").withMethod("GET") .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); @@ -167,9 +171,15 @@ public void testGetPersonSuccess() { assertThat(voPerson.get().getFirstName(), is("IRWIN")); assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); - assertThat(voPerson.get().getParticipations(), hasSize(1)); + assertThat(voPerson.get().getParticipations(), hasSize(2)); - ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); + List sortedParticipations = voPerson.get() + .getParticipations() + .stream() + .sorted((p1, p2) -> p1.getExperiment().compareTo(p2.getExperiment())) + .collect(toList()); + + ParticipationDTO participation = sortedParticipations.get(0); assertThat(participation.getExperiment(), is("ATLAS")); assertThat(participation.getStartDate(), notNullValue()); @@ -202,10 +212,16 @@ public void testGetPersonByEmailSuccess() { assertThat(voPerson.get().getFirstName(), is("IRWIN")); assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); - assertThat(voPerson.get().getParticipations(), hasSize(1)); + assertThat(voPerson.get().getParticipations(), hasSize(2)); - ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); + List sortedParticipations = voPerson.get() + .getParticipations() + .stream() + .sorted((p1, p2) -> p1.getExperiment().compareTo(p2.getExperiment())) + .collect(toList()); + ParticipationDTO participation = sortedParticipations.get(0); + assertThat(participation.getExperiment(), is("ATLAS")); assertThat(participation.getStartDate(), notNullValue()); assertThat(participation.getEndDate(), notNullValue()); @@ -216,15 +232,28 @@ public void testGetPersonByEmailSuccess() { assertThat(participation.getInstitute().getId(), is("000035")); assertThat(participation.getInstitute().getTown(), is("Some place 35")); assertThat(participation.getInstitute().getCountry(), is("IT")); + + participation = sortedParticipations.get(1); + + assertThat(participation.getExperiment(), is("CMS")); + assertThat(participation.getStartDate(), notNullValue()); + assertThat(participation.getEndDate(), notNullValue()); + assertThat(participation.isValidAtInstant(NOW), is(false)); + + assertThat(participation.getInstitute(), notNullValue()); + assertThat(participation.getInstitute().getName(), is("Institute 35")); + assertThat(participation.getInstitute().getId(), is("000035")); + assertThat(participation.getInstitute().getTown(), is("Some place 35")); + assertThat(participation.getInstitute().getCountry(), is("IT")); } @Test public void testHasValidExperimentParticipationSuccess() { - mockServer.when(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET"), once()) + mockServer.when(request("/api/VOPersons/participation/atlas/valid/1").withMethod("GET"), once()) .respond(response("true")); assertThat(apiService.hasValidExperimentParticipation(1), is(true)); - mockServer.verify(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET") + mockServer.verify(request("/api/VOPersons/participation/atlas/valid/1").withMethod("GET") .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); @@ -250,7 +279,7 @@ public void testGetPersonByVomsUser() { mockServer.when(request("/api/VOPersons/1").withMethod("GET"), exactly(2)) .respond(response(VO_PERSON_1_JSON)); - mockServer.when(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET"), once()) + mockServer.when(request("/api/VOPersons/participation/atlas/valid/1").withMethod("GET"), once()) .respond(response("true")); VOMSUser user = new VOMSUser(); @@ -265,27 +294,14 @@ public void testGetPersonByVomsUser() { assertThat(voPerson.get().getFirstName(), is("IRWIN")); assertThat(voPerson.get().getEmail(), is("IRWIN.MARPLE.1@mail.example")); assertThat(voPerson.get().getPhysicalEmail(), is("MARPLE.1@cern.ch")); - assertThat(voPerson.get().getParticipations(), hasSize(1)); - - ParticipationDTO participation = voPerson.get().getParticipations().iterator().next(); - - assertThat(participation.getExperiment(), is("ATLAS")); - assertThat(participation.getStartDate(), notNullValue()); - assertThat(participation.getEndDate(), notNullValue()); - assertThat(participation.isValidAtInstant(NOW), is(true)); - - assertThat(participation.getInstitute(), notNullValue()); - assertThat(participation.getInstitute().getName(), is("Institute 35")); - assertThat(participation.getInstitute().getId(), is("000035")); - assertThat(participation.getInstitute().getTown(), is("Some place 35")); - assertThat(participation.getInstitute().getCountry(), is("IT")); + assertThat(voPerson.get().getParticipations(), hasSize(2)); mockServer.verify(request("/api/VOPersons/1").withMethod("GET") .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); assertThat(apiService.hasValidExperimentParticipation(user), is(true)); - mockServer.verify(request("/api/VOPersons/participation/cms/valid/1").withMethod("GET") + mockServer.verify(request("/api/VOPersons/participation/atlas/valid/1").withMethod("GET") .withHeader("Authorization", "basic dXNlcjpwYXNzd29yZA==")); } diff --git a/voms-admin-server/src/test/resources/cern/json/voPerson1.json b/voms-admin-server/src/test/resources/cern/json/voPerson1.json index c19061e9..0b5b4fe1 100644 --- a/voms-admin-server/src/test/resources/cern/json/voPerson1.json +++ b/voms-admin-server/src/test/resources/cern/json/voPerson1.json @@ -13,8 +13,19 @@ "country": "IT" }, "experiment": "ATLAS", - "startDate": "2008-02-05", + "startDate": "2012-02-05", "endDate": "2022-01-01" + }, + { + "institute": { + "id": "000035", + "name": "Institute 35", + "town": "Some place 35", + "country": "IT" + }, + "experiment": "CMS", + "startDate": "2008-02-05", + "endDate": "2012-01-01" } ] } \ No newline at end of file From 0e3b1516c48c670c3f1a414f54deb66c33afd7a7 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Sun, 24 May 2020 15:53:43 +0200 Subject: [PATCH 43/63] Add voms-vo-ctl utility To manage vo deployment outside of init scripts (not available on CENTOS7/8) --- .../resources/scripts/init/voms-vo-ctl.sh | 173 ++++++++++++++++++ voms-admin-server/src/assemble/tarball.xml | 8 + 2 files changed, 181 insertions(+) create mode 100755 voms-admin-server/resources/scripts/init/voms-vo-ctl.sh diff --git a/voms-admin-server/resources/scripts/init/voms-vo-ctl.sh b/voms-admin-server/resources/scripts/init/voms-vo-ctl.sh new file mode 100755 index 00000000..1570f942 --- /dev/null +++ b/voms-admin-server/resources/scripts/init/voms-vo-ctl.sh @@ -0,0 +1,173 @@ +#!/bin/bash +if [ -n "${VERBOSE}" ]; then + set -x +fi +## return value +RETVAL=0 + +conf_dir="/etc/voms-admin/" +deploy_dir="/var/lib/voms-admin/vo.d" +configured_vos=$(find ${conf_dir} -maxdepth 1 -mindepth 1 -type d -exec basename {} \;) + +deploy_vos() { + vos=$1 + + if [ -z "$vos" ]; then + vos=$configured_vos + fi + + for vo in $vos; do + if [ $# -gt 1 ]; then + echo -n "Deploying vo($vo): " + fi + check_vo_name "$vo" + if [ -f $deploy_dir/$vo ]; then + if [ $# -gt 1 ]; then + success "already deployed" + fi + else + touch $deploy_dir/$vo + if [ $# -gt 1 ]; then + success + fi + fi + done +} + +undeploy_vos() { + vos=$1 + + if [ -z "$vos" ]; then + vos=$configured_vos + fi + + for vo in $vos; do + if [ $# -gt 1 ]; then + echo -n "Undeploying vo($vo): " + fi + if [ -f $deploy_dir/$vo ]; then + rm -f $deploy_dir/$vo + if [ $# -gt 1 ]; then + success + fi + else + if [ $# -gt 1 ]; then + success "was not deployed" + fi + fi + done +} + +check_vo_name() { + + for v in $configured_vos; do + [ "$v" = "$1" ] && return 0 + done + + failure "not configured" + exit 1 + +} + +deploy_dir_is_empty(){ + deployed_vos=`find $deploy_dir -maxdepth 1 -mindepth 1 -type f -exec basename {} \;` + if [ -z "$deployed_vos" ]; then + return 0; + else + return 1; + fi +} + +list(){ + + if [ -z "$configured_vos" ]; then + echo "no configured VO found" + return 0; + fi + + for v in ${configured_vos}; do + echo -n "$v" + if [ -f "${deploy_dir}/$v" ]; then + echo " (deployed)" + else + echo " (not deployed)" + fi + done +} + +init(){ + deploy_dir_is_empty + if [ $? -eq 0 ]; then + deploy_vos "$configured_vos" "verbose" + else + deployed_vos=`find $deploy_dir -maxdepth 1 -mindepth 1 -type f -exec basename {} \; | sort` + echo "Deployed VOs:" + for v in $deployed_vos; do + echo " $v" + done + fi + success +} + +success() +{ + + if [ ! -z "$1" ]; then + echo -n "$1" + fi + + RES_COL=60 + echo -en "\\033[${RES_COL}G" + echo -n "[ " + echo -en "\\033[1;32m" + echo -n OK + echo -en "\\033[0;39m" + echo -n " ]" + echo -ne "\r" + echo + + return 0 +} + + +failure() +{ + rc=$? + + if [ ! -z "$1" ]; then + echo -n "$1" + fi + + RES_COL=60 + echo -en "\\033[${RES_COL}G" + echo -n "[" + echo -en "\\033[1;31m" + echo -n FAILED + echo -en "\\033[0;39m" + echo -n "]" + echo -ne "\r" + echo + + return $rc +} + +case "$1" in + list) + list + ;; + + deploy) + deploy_vos "$2" "verbose" + ;; + + undeploy) + undeploy_vos "$2" "verbose" + ;; + + *) + echo "Usage: $0 {list|deploy|undeploy}" + RETVAL=1 + ;; +esac + +exit $RETVAL diff --git a/voms-admin-server/src/assemble/tarball.xml b/voms-admin-server/src/assemble/tarball.xml index 0f20530a..adee81f8 100644 --- a/voms-admin-server/src/assemble/tarball.xml +++ b/voms-admin-server/src/assemble/tarball.xml @@ -130,6 +130,14 @@ 0644 + + + resources/scripts/init/voms-vo-ctl.sh + /usr/sbin + voms-vo-ctl + 0755 + + resources/scripts/configure/voms_configure.py /usr/sbin From 9be8f3ee1e4fa1a6034f4ec0b3f0ee7339fabb20 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Sun, 24 May 2020 17:26:25 +0200 Subject: [PATCH 44/63] Fixed inconsistency in pom.xml Which caused classloading issues on deployments from RPMs built in CI. --- voms-admin-server/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index eea676ed..bd8f0b58 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -539,7 +539,8 @@ WEB-INF/classes/logback*.xml, WEB-INF/lib/javax*.jar, - WEB-INF/lib/jetty-*.jar, + WEB-INF/lib/jetty-all-server*.jar, + WEB-INF/lib/jetty-jsp-*.jar, WEB-INF/lib/bcmail-*.jar, WEB-INF/lib/bcprov-*.jar, WEB-INF/lib/canl-*.jar, From 51b84022dc5e15f4d48f8e47e97267ab80d020ce Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Fri, 28 Aug 2020 19:23:31 +0200 Subject: [PATCH 45/63] More work towards 3.8.0 --- .../scripts/configure/voms-clean-tlr-util | 6 + .../VOMSConfigurationConstants.java | 114 +++++++++++------- .../security/voms/admin/core/VOMSService.java | 11 +- .../user_cleanup/ExpiredUserCleanupTask.java | 37 ++++-- .../integration/cern/HrDbConfigurator.java | 6 +- .../admin/integration/cern/HrDbSyncTask.java | 4 +- .../integration/cern/HrDefaultHandler.java | 22 +++- .../cern/HttpClientHrDbApiService.java | 21 +++- .../cern/VoPersonNotFoundError.java | 14 +++ .../orgdb/DefaultSyncStrategy.java | 4 +- .../LogOnlyExpiredParticipationStrategy.java | 2 +- .../admin/persistence/dao/VOMSUserDAO.java | 26 ++++ .../dao/generic/AuditSearchDAO.java | 4 +- .../persistence/dao/generic/TaskDAO.java | 3 + .../hibernate/AuditSearchDAOHibernate.java | 8 +- .../dao/hibernate/TaskDAOHibernate.java | 7 ++ .../persistence/model/task/SignAUPTask.java | 3 - .../admin/persistence/model/task/Task.java | 23 +--- .../tools/CleanupTaskLogRecords.java | 110 +++++++++++++++++ .../integration/hr/HrDefaultHandlerTest.java | 42 +++++-- voms-container/pom.xml | 16 ++- 21 files changed, 368 insertions(+), 115 deletions(-) create mode 100644 voms-admin-server/resources/scripts/configure/voms-clean-tlr-util create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java create mode 100644 voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java diff --git a/voms-admin-server/resources/scripts/configure/voms-clean-tlr-util b/voms-admin-server/resources/scripts/configure/voms-clean-tlr-util new file mode 100644 index 00000000..6c575d2f --- /dev/null +++ b/voms-admin-server/resources/scripts/configure/voms-clean-tlr-util @@ -0,0 +1,6 @@ +#!/bin/bash + +VOMS_ADMIN_JAR=${VOMS_ADMIN_JAR:-/usr/share/java/voms-admin.jar} + +java -cp ${VOMS_ADMIN_JAR}':/var/lib/voms-admin/lib/*:/var/lib/voms-admin/tools' \ + org.glite.security.voms.admin.persistence.tools.CleanupTaskLogRecords $@ diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java index 42cde558..4fbc7bcd 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/configuration/VOMSConfigurationConstants.java @@ -22,7 +22,8 @@ public interface VOMSConfigurationConstants { */ public static final String VO_NAME = "voms.vo.name"; - public static final String LOCALHOST_DEFAULTS_TO_LOCAL_ADMIN = "voms.localhost.defaults.to.local.admin"; + public static final String LOCALHOST_DEFAULTS_TO_LOCAL_ADMIN = + "voms.localhost.defaults.to.local.admin"; public static final String READONLY = "voms.readonly"; @@ -49,25 +50,35 @@ public interface VOMSConfigurationConstants { public static final String NOTIFICATION_RETRY_PERIOD = "voms.notification.retry_period"; public static final String NOTIFICATION_DISABLED = "voms.notification.disable"; - public static final String VO_MEMBERSHIP_EXPIRED_REQ_PURGER_PERIOD = "voms.request.vo_membership.expired_request_purger.period"; - public static final String UNCONFIRMED_REQUESTS_EXPIRATION_TIME = "voms.request.vo_membership.lifetime"; - public static final String VO_MEMBERSHIP_UNCONFIRMED_REQ_WARN_POLICY = "voms.request.vo_membership.warn_when_expired"; + public static final String VO_MEMBERSHIP_EXPIRED_REQ_PURGER_PERIOD = + "voms.request.vo_membership.expired_request_purger.period"; + public static final String UNCONFIRMED_REQUESTS_EXPIRATION_TIME = + "voms.request.vo_membership.lifetime"; + public static final String VO_MEMBERSHIP_UNCONFIRMED_REQ_WARN_POLICY = + "voms.request.vo_membership.warn_when_expired"; /** - * This configuration flag controls the user's ability to request attributes - * at VO registration time. + * This configuration flag controls the user's ability to request attributes at VO registration + * time. */ - public static final String VO_MEMBERSHIP_ENABLE_ATTRIBUTES_REQUEST = "voms.request.vo_membership.enable_attribute_requests"; - public static final String VO_MEMBERSHIP_REQUIRE_GROUP_MANAGER_SELECTION = "voms.request.vo_membership.require_group_manager_selection"; - + public static final String VO_MEMBERSHIP_ENABLE_ATTRIBUTES_REQUEST = + "voms.request.vo_membership.enable_attribute_requests"; + public static final String VO_MEMBERSHIP_REQUIRE_GROUP_MANAGER_SELECTION = + "voms.request.vo_membership.require_group_manager_selection"; + public static final String GROUP_MANAGER_ROLE_NAME = "voms.request.group_manager_role"; - - public static final String USER_MAX_RESULTS_PER_PAGE = "voms.pagination.user.max.results.per.page"; - public static final String ATTRIBUTES_MAX_RESULTS_PER_PAGE = "voms.pagination.attributes.max.results.per.page"; - public static final String GROUP_MAX_RESULTS_PER_PAGE = "voms.pagination.group.max.results.per.page"; - public static final String ROLE_MAX_RESULTS_PER_PAGE = "voms.pagination.role.max.results.per.page"; + + public static final String USER_MAX_RESULTS_PER_PAGE = + "voms.pagination.user.max.results.per.page"; + public static final String ATTRIBUTES_MAX_RESULTS_PER_PAGE = + "voms.pagination.attributes.max.results.per.page"; + public static final String GROUP_MAX_RESULTS_PER_PAGE = + "voms.pagination.group.max.results.per.page"; + public static final String ROLE_MAX_RESULTS_PER_PAGE = + "voms.pagination.role.max.results.per.page"; public static final String REGISTRATION_SERVICE_ENABLED = "voms.registration.enabled"; - public static final String READ_ACCESS_FOR_AUTHENTICATED_CLIENTS = "voms.read-access-for-authenticated-clients"; + public static final String READ_ACCESS_FOR_AUTHENTICATED_CLIENTS = + "voms.read-access-for-authenticated-clients"; /** * VERSION Properties */ @@ -80,14 +91,15 @@ public interface VOMSConfigurationConstants { */ public static final String GRID_AUP_URL = "voms.aup.grid_aup.initial_url"; public static final String VO_AUP_URL = "voms.aup.vo_aup.initial_url"; - + public static final String SIGN_AUP_TASK_LIFETIME = "voms.aup.sign_aup_task_lifetime"; public static final int SIGN_AUP_TASK_LIFETIME_DEFAULT_VALUE = 15; - - public static final String[] SIGN_AUP_TASK_REMINDERS_DEFAULT_VALUE = {"7","3","1"}; + + public static final String[] SIGN_AUP_TASK_REMINDERS_DEFAULT_VALUE = {"7", "3", "1"}; public static final String SIGN_AUP_TASK_REMINDERS = "voms.aup.sign_aup_task_reminders"; - - public static final String REQUIRE_AUP_SIGNATURE_FOR_CREATED_USERS = "voms.aup.require_signature_for_created_users"; + + public static final String REQUIRE_AUP_SIGNATURE_FOR_CREATED_USERS = + "voms.aup.require_signature_for_created_users"; public static final String SIGN_AUP_EXTENDS_MEMBERSHIP = "voms.aup.signature_extends_membership"; /** @@ -95,11 +107,15 @@ public interface VOMSConfigurationConstants { */ public static final String DEFAULT_MEMBERSHIP_LIFETIME = "voms.membership.default_lifetime"; public static final String MEMBERSHIP_CHECK_PERIOD = "voms.task.membership_check.period"; - public static final String DISABLE_MEMBERSHIP_EXPIRATION_WARNING="voms.membership.disable_expiration_warning"; - public static final String MEMBERSHIP_EXPIRATION_WARNING_PERIOD = "voms.membership.expiration_warning_period"; + public static final String DISABLE_MEMBERSHIP_EXPIRATION_WARNING = + "voms.membership.disable_expiration_warning"; + public static final String MEMBERSHIP_EXPIRATION_WARNING_PERIOD = + "voms.membership.expiration_warning_period"; public static final String MEMBERSHIP_EXPIRATION_WARNING_PERIOD_DEFAULT_VALUE = "15"; - public static final String MEMBERSHIP_EXPIRATION_GRACE_PERIOD = "voms.membership.expiration_grace_period"; - public static final String NOTIFICATION_WARNING_RESEND_PERIOD = "voms.membership.notification_resend_period"; + public static final String MEMBERSHIP_EXPIRATION_GRACE_PERIOD = + "voms.membership.expiration_grace_period"; + public static final String NOTIFICATION_WARNING_RESEND_PERIOD = + "voms.membership.notification_resend_period"; public static final String PRESERVE_EXPIRED_MEMBERS = "voms.preserve_expired_members"; public static final String PRESERVE_AUP_FAILING_MEMBERS = "voms.preserve_aup_failing_members"; public static final String DISABLE_MEMBERSHIP_END_TIME = "voms.disable_membership_end_time"; @@ -110,14 +126,17 @@ public interface VOMSConfigurationConstants { public static final String VOMS_SERVICE_CERT_FILE = "voms.service.cert"; public static final String VOMS_SERVICE_KEY_FILE = "voms.service.key"; public static final String VOMS_SAML_MAX_ASSERTION_LIFETIME = "voms.saml.max_assertion_lifetime"; - public static final String VOMS_AA_COMPULSORY_GROUP_MEMBERSHIP = "voms.aa.compulsory_group_membership"; + public static final String VOMS_AA_COMPULSORY_GROUP_MEMBERSHIP = + "voms.aa.compulsory_group_membership"; public static final String VOMS_AA_SAML_ACTIVATE_ENDPOINT = "voms.aa.activate_saml_endpoint"; public static final String VOMS_AA_X509_ACTIVATE_ENDPOINT = "voms.aa.x509.activate_endpoint"; public static final String VOMS_AA_X509_MAX_AC_VALIDITY = "voms.aa.x509.max_ac_validity"; public static final String VOMS_AA_X509_PRINT_STATS_PERIOD = "voms.aa.x509.print_stats_period"; - public static final String VOMS_AA_X509_LEGACY_FQAN_ENCODING = "voms.aa.x509.legacy_fqan_encoding"; + public static final String VOMS_AA_X509_LEGACY_FQAN_ENCODING = + "voms.aa.x509.legacy_fqan_encoding"; - public static final String VOMS_UNAUTHENTICATED_CLIENT_PERMISSION_MASK = "voms.unauthenticated_client_permission_mask"; + public static final String VOMS_UNAUTHENTICATED_CLIENT_PERMISSION_MASK = + "voms.unauthenticated_client_permission_mask"; /** * External validation plugin Properties @@ -132,8 +151,10 @@ public interface VOMSConfigurationConstants { */ public static final String VOMS_INTERNAL_REGISTRATION_TYPE = "___voms.regitration.type"; - public static final String VOMS_INTERNAL_RO_PERSONAL_INFORMATION = "___voms.read-only-personal-information"; - public static final String VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE = "___voms.read-only-membership-expiration"; + public static final String VOMS_INTERNAL_RO_PERSONAL_INFORMATION = + "___voms.read-only-personal-information"; + public static final String VOMS_INTERNAL_RO_MEMBERSHIP_EXPIRATION_DATE = + "___voms.read-only-membership-expiration"; /** * Executor service properties @@ -146,8 +167,8 @@ public interface VOMSConfigurationConstants { public static final String VOMS_CSRF_GUARD_LOG_ONLY = "voms.csrf.log_only"; /** - * VOMS Admin service hostname. This property is needed to properly compute - * the service address when sending out email notifications. + * VOMS Admin service hostname. This property is needed to properly compute the service address + * when sending out email notifications. */ public static final String VOMS_SERVICE_HOSTNAME = "voms.hostname"; public static final String VOMS_SERVICE_PORT = "voms.port"; @@ -155,38 +176,45 @@ public interface VOMSConfigurationConstants { /** * The local path where monitored stats properties will be stored. */ - public static final String MONITORING_USER_STATS_BASE_PATH = "voms.monitoring.user_stats_base_path"; + public static final String MONITORING_USER_STATS_BASE_PATH = + "voms.monitoring.user_stats_base_path"; /** * The file name of the monitored stats properties. */ - public static final String MONITORING_USER_STATS_FILE_NAME = "voms.monitoring.user_stats_filename"; + public static final String MONITORING_USER_STATS_FILE_NAME = + "voms.monitoring.user_stats_filename"; /** * How often (in minutes) the stats will be updated * */ - public static final String MONITORING_USER_STATS_UPDATE_PERIOD = "voms.monitoring.user_stats_period"; + public static final String MONITORING_USER_STATS_UPDATE_PERIOD = + "voms.monitoring.user_stats_period"; /** * Whether to skip the checks on certificate issuers when authenticating clients */ public static final String SKIP_CA_CHECK = "voms.skip_ca_check"; - + /** * Should permission cache be disabled? */ public static final String PERMISSION_CACHE_DISABLE = "voms.permission_cache.disable"; - + /** - * comma-separated list of the personal information fields required at registration + * comma-separated list of the personal information fields required at registration */ public static final String PI_REQUIRED_FIELDS = "voms.personal_info.required_fields"; - + public static final String PI_REQUIRED_FIELDS_DEFAULT = "institution,address,phoneNumber"; - - public static final String EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD= "voms.expired_user_cleanup_task.run_period_sec"; - - public static final String EXPIRED_USER_CLEANUP_TASK_CLEANUP_AFTER_DAYS= "voms.expired_user_cleanup_task.cleanup_after_days"; - + + + public static final String EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD = + "voms.expired_user_cleanup_task.run_period_sec"; + public static final String EXPIRED_USER_CLEANUP_TASK_CLEANUP_AFTER_DAYS = + "voms.expired_user_cleanup_task.cleanup_after_days"; + public static final String EXPIRED_USER_CLEANUP_TASK_BATCH_SIZE = + "voms.expired_user_cleanup_task.batch_size"; + } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java index 582de3eb..3c07b210 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/VOMSService.java @@ -214,12 +214,15 @@ protected static void startBackgroundTasks() { es.scheduleAtFixedRate(new PermissionCacheStatsLogger(true), 1, 60, TimeUnit.SECONDS); - ExpiredUserCleanupTask userCleanupTask = - new ExpiredUserCleanupTask(new DefaultCleanupUserLookupStrategy(conf)); + int expiredUserCleanupBatchSize = + conf.getInt(VOMSConfigurationConstants.EXPIRED_USER_CLEANUP_TASK_BATCH_SIZE, 10); - es.startBackgroundTask(userCleanupTask, EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD, - TimeUnit.HOURS.toSeconds(4)); + ExpiredUserCleanupTask userCleanupTask = new ExpiredUserCleanupTask( + new DefaultCleanupUserLookupStrategy(conf), expiredUserCleanupBatchSize); + es.startBackgroundTask(userCleanupTask, EXPIRED_USER_CLEANUP_TASK_RUN_PERIOD, + TimeUnit.MINUTES.toSeconds(30)); + } protected static void startNotificationService() { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java index 80d6d77e..2330bd32 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/core/tasks/user_cleanup/ExpiredUserCleanupTask.java @@ -27,12 +27,16 @@ public class ExpiredUserCleanupTask implements Runnable, RegistrationServiceTask { public static final Logger LOG = LoggerFactory.getLogger(ExpiredUserCleanupTask.class); + public static final int DEFAULT_BATCH_SIZE = 50; + final CleanupUserLookupStrategy lookupStrategy; + int batchSize = DEFAULT_BATCH_SIZE; VOMSUserDAO dao; - EventManager eventManager; + EventManager manager; - public ExpiredUserCleanupTask(CleanupUserLookupStrategy lookupStrategy) { + public ExpiredUserCleanupTask(CleanupUserLookupStrategy lookupStrategy, int batchSize) { this.lookupStrategy = lookupStrategy; + this.batchSize = batchSize; } @Override @@ -42,27 +46,38 @@ public void run() { dao = VOMSUserDAO.instance(); } - if (eventManager == null) { - eventManager = EventManager.instance(); + if (manager == null) { + manager = EventManager.instance(); } + int processedUsers = 0; ScrollableResults userCursor = lookupStrategy.findUsersEligibleForCleanup(); - while (userCursor.next()) { + while (userCursor.next() && processedUsers < batchSize) { VOMSUser user = (VOMSUser) userCursor.get(0); - LOG.debug("Cleaning up user '{}' who expired on '{}'", user.getShortName(), - user.getEndTime()); - dao.delete(user); - eventManager.dispatch(new UserCleanedUpEvent(user)); + if (user.getTasks().isEmpty()) { + LOG.info("Deleting user '{} ({})' who expired on '{}'", user.getShortName(), user.getId(), + user.getEndTime()); + + dao.delete(user); + manager.dispatch(new UserCleanedUpEvent(user)); + } else { + LOG.info("Cleaning up tasks for user '{} ({})' who expired on '{}'", user.getShortName(), user.getId(), + user.getEndTime()); + dao.deleteTasks(user); + } + + processedUsers++; } } + public void setDao(VOMSUserDAO dao) { this.dao = dao; } - public void setEventManager(EventManager eventManager) { - this.eventManager = eventManager; + public void setManager(EventManager manager) { + this.manager = manager; } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java index 42cff7e5..88276ad2 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbConfigurator.java @@ -46,9 +46,6 @@ public class HrDbConfigurator extends AbstractPluginConfigurator public static final String DEFAULT_CONFIG_FILE_NAME = "hr.properties"; - public static final String HR_DB_EXPERIMENT_NAME_PROPERTY = "experiment_name"; - public static final String HR_DB_MEMBERSHIP_CHECK_PERIOD_IN_SECONDS = "membership_check.period"; - public static final String HR_DB_REGISTRATION_TYPE = "hr"; private Clock clock; @@ -179,7 +176,8 @@ public void configure() throws VOMSPluginConfigurationException { validationManager.setRequestValidationContext( requestValidatorFactory.newHrDbRequestValidator(hrConfig, apiService)); - LOG.info("HR DB request validator registered succesfully"); + LOG.info("HR DB request validator registered succesfully. Syncing against HR db experiment {}", + hrConfig.getExperimentName()); if (hrConfig.getMembesrshipCheck().isEnabled()) { scheduleSyncTask(hrConfig, diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java index 41a991b6..f18c96e0 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbSyncTask.java @@ -67,11 +67,11 @@ public void run() { } else { missingRecordHandler.handleMissingHrRecord(user); } - + } catch (HrDbError apiError) { LOG.error("Error querying HR Db API for user {}: {}", user.getShortName(), apiError.getMessage()); - + if (LOG.isDebugEnabled()) { LOG.error(apiError.getMessage(), apiError); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java index 783be33a..93bbf414 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDefaultHandler.java @@ -15,6 +15,8 @@ */ package org.glite.security.voms.admin.integration.cern; +import static java.util.Objects.isNull; + import java.time.Clock; import java.time.Instant; import java.util.Date; @@ -62,10 +64,12 @@ protected void restoreUserIfNeeded(VOMSUser u) { if (u.getSuspensionReasonCode() == SuspensionReason.MEMBERSHIP_EXPIRATION || u.getSuspensionReason().startsWith("OrgDB: ")) { + LOG.info("Restoring user {} - {} which was previously suspended", u.getShortName(), + u.getOrgDbId()); + manager.restoreUser(u); } } - } @@ -82,24 +86,34 @@ public void synchronizeMembershipInformation(VOMSUser user, VOPersonDTO voPerson String orgDbEmailAddress = Optional.ofNullable(voPerson.getPhysicalEmail()).orElse(voPerson.getEmail()); - - user.setEmailAddress(orgDbEmailAddress.toLowerCase()); + + if (!isNull(orgDbEmailAddress)) { + user.setEmailAddress(orgDbEmailAddress.toLowerCase()); + } else { + LOG.warn("Email address not found from record {}", voPerson.getId()); + } Optional participation = voPerson.findValidParticipationForExperiment(now, config.getExperimentName()); if (participation.isPresent()) { + LOG.info("Setting user {} - {} end time from partecipation end time: {}", user.getShortName(), + voPerson.getId(), participation.get().getEndDate()); user.setEndTime(participation.get().getEndDate()); restoreUserIfNeeded(user); } else { handleExpiredParticipation(user, voPerson); } - + LOG.info("Synced user {} against record {}", user.getShortName(), voPerson.getId()); } @Override public void handleExpiredParticipation(VOMSUser u, VOPersonDTO voPerson) { + + LOG.info("No valid experiment participation found for {} found in: {}", u.getShortName(), + voPerson.getParticipations()); + Instant now = clock.instant(); u.setEndTime(Date.from(now)); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java index e1129005..5dea988b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HttpClientHrDbApiService.java @@ -108,10 +108,16 @@ protected void handleExchange(ContentExchange ce) { if (HttpExchange.STATUS_COMPLETED == exchangeStatus) { if (ce.getResponseStatus() != 200) { - + @SuppressWarnings("unchecked") - ErrorDTO error = ErrorDTO.fromJsonMap((Map) JSON.parse(ce.getResponseContent())); - throw new HrDbExchangeError(ce.getResponseStatus(), error.getErrorMessage()); + ErrorDTO error = + ErrorDTO.fromJsonMap((Map) JSON.parse(ce.getResponseContent())); + + if (ce.getResponseStatus() == 404) { + throw new VoPersonNotFoundError(ce.getResponseStatus(), error.getErrorMessage()); + } else { + throw new HrDbExchangeError(ce.getResponseStatus(), error.getErrorMessage()); + } } } else if (HttpExchange.STATUS_EXPIRED == exchangeStatus) { throw new HrDbError("Error contacting the HR DB api: request timeout exceeded"); @@ -167,8 +173,13 @@ public Optional lookupVomsUser(VOMSUser user) { Long orgDbId = user.getOrgDbId(); - if (!isNull(orgDbId)) { - return getVoPersonRecord(orgDbId); + try { + if (!isNull(orgDbId)) { + return getVoPersonRecord(orgDbId); + } + } catch (VoPersonNotFoundError e) { + LOG.warn("VO person not found for user {} ({}): {}", user.getShortName(), user.getId(), + e.getMessage()); } return Optional.empty(); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java new file mode 100644 index 00000000..a258b384 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java @@ -0,0 +1,14 @@ +package org.glite.security.voms.admin.integration.cern; + +public class VoPersonNotFoundError extends HrDbExchangeError { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public VoPersonNotFoundError(int responseStatus, String responseMessage) { + super(responseStatus, responseMessage); + } + +} diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/DefaultSyncStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/DefaultSyncStrategy.java index 5337d8c3..316b8895 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/DefaultSyncStrategy.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/DefaultSyncStrategy.java @@ -183,7 +183,7 @@ private void synchronizePersonalInformation(VOMSUser u, public void synchronizeMemberInformation(VOMSUser u, VOMSOrgDBPerson orgDbPerson, String experimentName, Participation validParticipation) { - log.debug( + log.info( "Synchronizing pariticipation data for user {} against orgdb record {} for experiment {}", new Object[] { u, orgDbPerson, experimentName }); @@ -191,7 +191,7 @@ public void synchronizeMemberInformation(VOMSUser u, log.warn("No valid participation found for user {}, orgdb record {} in experiment {}", new Object[] { u, orgDbPerson, experimentName}); } else { - log.debug("Participation found for user {}, orgdb record {} in experiment {}: {}", + log.info("Participation found for user {}, orgdb record {} in experiment {}: {}", new Object[] { u, orgDbPerson, experimentName, validParticipation}); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/LogOnlyExpiredParticipationStrategy.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/LogOnlyExpiredParticipationStrategy.java index 2665d753..a8928092 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/LogOnlyExpiredParticipationStrategy.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/orgdb/LogOnlyExpiredParticipationStrategy.java @@ -30,7 +30,7 @@ public class LogOnlyExpiredParticipationStrategy implements public void handleOrgDbExpiredParticipation(VOMSUser u, VOMSOrgDBPerson orgDBPerson, String experimentName) { - log.debug("User {} participation for experiment {} has expired.", u, + log.info("User {} participation for experiment {} has expired.", u, experimentName); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index 4059858d..bb0f2bcb 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -88,6 +88,31 @@ public static VOMSUserDAO instance() { private VOMSUserDAO() { } + + + public void deleteTasks(VOMSUser user) { + + String deleteTLRs = "delete from task_log_record where task_id in ( select t.task_id from " + + "task t, usr u where t.usr_id = u.userid and u.userid = :userId )"; + HibernateFactory.getSession() + .createSQLQuery(deleteTLRs) + .setLong("userId", user.getId()) + .executeUpdate(); + + String deleteSATs = "delete from sign_aup_task where task_id in (select t.task_id from " + + "task t, usr u where t.usr_id = u.userid and u.userid = :userId )"; + HibernateFactory.getSession() + .createSQLQuery(deleteSATs) + .setLong("userId", user.getId()) + .executeUpdate(); + + String deleteTasks = "delete from task where usr_id = :userId"; + HibernateFactory.getSession() + .createSQLQuery(deleteTasks) + .setLong("userId", user.getId()) + .executeUpdate(); + + } public void requestAUPReacceptance(VOMSUser user, AUP aup) { @@ -670,6 +695,7 @@ public VOMSUser delete(VOMSUser u) { u.getAttributes().clear(); u.getAupAcceptanceRecords().clear(); u.getPersonalInformations().clear(); + u.getTasks().clear(); HibernateFactory.getSession().delete(u); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/AuditSearchDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/AuditSearchDAO.java index 301bced8..67865ecf 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/AuditSearchDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/AuditSearchDAO.java @@ -27,13 +27,13 @@ public interface AuditSearchDAO extends GenericDAO { List findLatestEvents(int numEvents); - Integer countEvents(); + Long countEvents(); AuditLogSearchResults findEventsMatchingParams(AuditLogSearchParams sp); ScrollableAuditLogSearchResults scrollEventsMatchingParams( AuditLogSearchParams sp, ScrollMode scrollMode); - Integer countEventsMatchingParams(AuditLogSearchParams sp); + Long countEventsMatchingParams(AuditLogSearchParams sp); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/TaskDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/TaskDAO.java index 49b069da..71ba1c96 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/TaskDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/generic/TaskDAO.java @@ -19,6 +19,7 @@ import java.util.List; import org.glite.security.voms.admin.persistence.model.AUP; +import org.glite.security.voms.admin.persistence.model.VOMSUser; import org.glite.security.voms.admin.persistence.model.request.Request; import org.glite.security.voms.admin.persistence.model.task.ApproveUserRequestTask; import org.glite.security.voms.admin.persistence.model.task.SignAUPTask; @@ -41,5 +42,7 @@ public interface TaskDAO extends GenericDAO { void removeAllTasks(); List getActiveTasks(); + + void removeAllUserTasks(VOMSUser user); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/AuditSearchDAOHibernate.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/AuditSearchDAOHibernate.java index 81c44715..81c4285d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/AuditSearchDAOHibernate.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/AuditSearchDAOHibernate.java @@ -53,11 +53,11 @@ public List findLatestEvents(int numEvents) { } @Override - public Integer countEvents() { + public Long countEvents() { Criteria crit = createCriteria(); crit.setProjection(Projections.rowCount()); - return (Integer) crit.uniqueResult(); + return (Long) crit.uniqueResult(); } protected Criteria buildCriteriaFromParams(AuditLogSearchParams sp) { @@ -158,7 +158,7 @@ public ScrollableAuditLogSearchResults scrollEventsMatchingParams( } @Override - public Integer countEventsMatchingParams(AuditLogSearchParams sp) { + public Long countEventsMatchingParams(AuditLogSearchParams sp) { Criteria crit = buildCriteriaFromParams(sp); crit.setProjection(Projections.rowCount()); @@ -175,7 +175,7 @@ public Integer countEventsMatchingParams(AuditLogSearchParams sp) { crit.setFirstResult(0); crit.setMaxResults(100); - return (Integer) crit.uniqueResult(); + return (Long) crit.uniqueResult(); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/TaskDAOHibernate.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/TaskDAOHibernate.java index 6fd16f96..380f9c9d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/TaskDAOHibernate.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/hibernate/TaskDAOHibernate.java @@ -27,6 +27,7 @@ import org.glite.security.voms.admin.persistence.dao.generic.TaskTypeDAO; import org.glite.security.voms.admin.persistence.error.VOMSDatabaseException; import org.glite.security.voms.admin.persistence.model.AUP; +import org.glite.security.voms.admin.persistence.model.VOMSUser; import org.glite.security.voms.admin.persistence.model.request.Request; import org.glite.security.voms.admin.persistence.model.task.ApproveUserRequestTask; import org.glite.security.voms.admin.persistence.model.task.SignAUPTask; @@ -136,5 +137,11 @@ public List findActiveSignAUPTasks() { return crit.list(); } + @Override + public void removeAllUserTasks(VOMSUser user) { + + + } + } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/SignAUPTask.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/SignAUPTask.java index d76091ec..341de6d7 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/SignAUPTask.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/SignAUPTask.java @@ -55,9 +55,6 @@ public SignAUPTask(TaskType tt, AUP a, Date expiryDate) { this.expiryDate = expiryDate; creationDate = new Date(); status = TaskStatus.CREATED; - - addLogRecord(getCreationDate()); - } /** diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/Task.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/Task.java index d39aa282..7bdce5dc 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/Task.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/task/Task.java @@ -68,7 +68,7 @@ public enum TaskStatus { @Column(nullable = false) TaskStatus status; - @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "task") + @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "task", orphanRemoval = true) @Sort(type = SortType.NATURAL) @org.hibernate.annotations.Cascade( value = { org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) @@ -188,14 +188,10 @@ public void setCompleted() { setCompletionDate(new Date()); setStatus(TaskStatus.COMPLETED); - - addLogRecord(getCompletionDate()); } public void setExpired() { - setStatus(TaskStatus.EXPIRED); - addLogRecord(new Date()); } public boolean isExpired(){ @@ -289,23 +285,6 @@ public void setAdmin(VOMSAdmin admin) { this.admin = admin; } - protected void addLogRecord(Date d) { - - LogRecord r = new LogRecord(); - - r.setDate(d); - r.setEvent(getStatus()); - r.setTask(this); - - if (getUser() != null) - r.setUserDn(getUser().getDefaultCertificate().getSubjectString()); - if (getAdmin() != null) - r.setAdminDn(getAdmin().getDn()); - - getLogRecords().add(r); - - } - public long getDaysBeforeExpiration() { long now = new Date().getTime(); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java new file mode 100644 index 00000000..828b4dc9 --- /dev/null +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java @@ -0,0 +1,110 @@ +package org.glite.security.voms.admin.persistence.tools; + +import static java.lang.Long.parseLong; + +import org.glite.security.voms.admin.configuration.VOMSConfiguration; +import org.glite.security.voms.admin.configuration.VOMSConfigurationConstants; +import org.glite.security.voms.admin.persistence.DBUtil; +import org.glite.security.voms.admin.persistence.HibernateFactory; +import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; +import org.glite.security.voms.admin.persistence.dao.lookup.LookupPolicyProvider; +import org.glite.security.voms.admin.persistence.model.VOMSUser; +import org.glite.security.voms.admin.servlets.InitSecurityContext; +import org.hibernate.ScrollableResults; +import org.hibernate.cfg.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CleanupTaskLogRecords implements Runnable { + + public static final Logger LOG = LoggerFactory.getLogger(CleanupTaskLogRecords.class); + + final String vo; + final long batchSize; + + public CleanupTaskLogRecords(String vo, long batchSize) { + this.vo = vo; + this.batchSize = batchSize; + } + + + + public static void usage() { + System.out.println("usage: cmd "); + System.exit(1); + } + + private void loadVomsAdminConfiguration() { + System.setProperty(VOMSConfigurationConstants.VO_NAME, vo); + VOMSConfiguration.load(null); + } + + public static void main(String[] args) { + if (args.length != 2) { + usage(); + } + + new CleanupTaskLogRecords(args[0], parseLong(args[1])).run(); + } + + private void initializeLookupPolicyProvider() { + + boolean skipCaCheck = + VOMSConfiguration.instance().getBoolean(VOMSConfigurationConstants.SKIP_CA_CHECK, false); + + LookupPolicyProvider.initialize(skipCaCheck); + + } + + @Override + public void run() { + loadVomsAdminConfiguration(); + initializeLookupPolicyProvider(); + Configuration hibernateConfig = DBUtil.loadHibernateConfiguration("/etc/voms-admin", vo); + + hibernateConfig.configure(); + HibernateFactory.initialize(hibernateConfig); + HibernateFactory.beginTransaction(); + try { + InitSecurityContext.setInternalAdminContext(); + VOMSUserDAO dao = VOMSUserDAO.instance(); + ScrollableResults expiredUsers = dao.findUsersExpiredSinceDays(100); + + long processedRecords = 0; + + while (expiredUsers.next() && processedRecords < batchSize) { + VOMSUser user = (VOMSUser) expiredUsers.get(0); + + LOG.info("Deleting user '{} ({})' tasks who expired on '{}'", user.getShortName(), + user.getId(), user.getEndTime()); + + String deleteTLRs = "delete from task_log_record where task_id in ( select t.task_id from " + + "task t, usr u where t.usr_id = u.userid and u.userid = :userId )"; + HibernateFactory.getSession() + .createSQLQuery(deleteTLRs) + .setLong("userId", user.getId()) + .executeUpdate(); + + String deleteSATs = "delete from sign_aup_task where task_id in (select t.task_id from " + + "task t, usr u where t.usr_id = u.userid and u.userid = :userId )"; + HibernateFactory.getSession() + .createSQLQuery(deleteSATs) + .setLong("userId", user.getId()) + .executeUpdate(); + + String deleteTasks = "delete from task where usr_id = :userId"; + HibernateFactory.getSession() + .createSQLQuery(deleteTasks) + .setLong("userId", user.getId()) + .executeUpdate(); + processedRecords++; + } + + HibernateFactory.commitTransaction(); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + HibernateFactory.rollbackTransaction(); + } + + } +} diff --git a/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java index 6cf441de..f5b80185 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java @@ -109,12 +109,21 @@ public void testMissingHrRecordLeadsToUserSuspension() { } @Test - public void testSynchStrategy() { + public void testSynchStrategyMultipleParticipations() { oneParticipation.setExperiment("experiment"); - oneParticipation.setStartDate(Date.from(ONE_WEEK_AGO)); - - voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + oneParticipation.setStartDate(Date.from(TWO_YEARS_AGO)); + oneParticipation.setEndDate(Date.from(ONE_YEAR_AGO)); + + anotherParticipation.setExperiment("experiment"); + anotherParticipation.setStartDate(Date.from(ONE_WEEK_AGO)); + + aThirdParticipation.setExperiment("another"); + oneParticipation.setStartDate(Date.from(TWO_YEARS_AGO)); + + + voPerson.setParticipations( + Sets.newHashSet(oneParticipation, anotherParticipation, aThirdParticipation)); handler.synchronizeMembershipInformation(user, voPerson); @@ -123,9 +132,28 @@ public void testSynchStrategy() { assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); assertThat(user.getEndTime(), nullValue()); - } + + @Test + public void testSynchStrategy() { + + oneParticipation.setExperiment("experiment"); + oneParticipation.setStartDate(Date.from(ONE_WEEK_AGO)); + + + voPerson.setParticipations(Sets.newHashSet(oneParticipation)); + + handler.synchronizeMembershipInformation(user, voPerson); + + assertThat(user.getName(), is("TEST")); + assertThat(user.getSurname(), is("USER")); + assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); + assertThat(user.getEndTime(), nullValue()); + + + } + @Test public void testSynchInvalidParticipation() { @@ -164,7 +192,7 @@ public void testDoNotRestoreSuspendedUserForOtherReason() { } @Test - public void testRestoreSuspendedUserDoToValidationError() { + public void testRestoreSuspendedUserDueToValidationError() { oneParticipation.setExperiment("experiment"); oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); @@ -187,7 +215,7 @@ public void testRestoreSuspendedUserDoToValidationError() { } @Test - public void testRestoreSuspendedUserDoToMembershipExpiration() { + public void testRestoreSuspendedUserDueToMembershipExpiration() { oneParticipation.setExperiment("experiment"); oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 69b5f271..4e94a615 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -148,11 +148,25 @@ com.google.guava guava - + commons-cli commons-cli + + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + + + + org.glassfish.jaxb + jaxb-runtime + 2.3.2 + + From 47961abcb2fa2522121a4e567effd51acb40aa51 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Sat, 29 Aug 2020 09:24:18 +0200 Subject: [PATCH 46/63] Align with EPEL location of voms mysql plugin --- .../scripts/configure/voms_shared.py | 207 +++++++++++------- 1 file changed, 122 insertions(+), 85 deletions(-) diff --git a/voms-admin-server/resources/scripts/configure/voms_shared.py b/voms-admin-server/resources/scripts/configure/voms_shared.py index 91d10d87..ada71321 100644 --- a/voms-admin-server/resources/scripts/configure/voms_shared.py +++ b/voms-admin-server/resources/scripts/configure/voms_shared.py @@ -21,62 +21,78 @@ __voms_version__ = "${pom.version}" __voms_prefix__ = "${package.prefix}" -import re, commands, exceptions, os.path, glob, platform +import re +import commands +import exceptions +import os.path +import glob +import platform + def mysql_util_cmd(command, options): db_cmd = "%s %s --dbauser %s --dbusername %s --dbpassword '%s' --dbname %s --dbhost %s --dbport %s --mysql-command %s" % (VOMSDefaults.voms_mysql_util, - command, - options.dbauser, - options.dbusername, - options.dbpassword, - options.dbname, - options.dbhost, - options.dbport, - options.mysql_command) - + command, + options.dbauser, + options.dbusername, + options.dbpassword, + options.dbname, + options.dbhost, + options.dbport, + options.mysql_command) + if options.dbapwdfile: dbapwd = open(options.dbapwdfile).read() options.dbapwd = dbapwd - + if options.dbapwd: db_cmd += " --dbapwd=%s" % options.dbapwd - + return db_cmd + def voms_add_admin_cmd(vo, cert, ignore_email=False): if ignore_email: return "%s %s" % (__voms_db_util_base_cmd(vo, "add-admin"), "--cert %s --ignore-cert-email" % cert) else: return "%s %s" % (__voms_db_util_base_cmd(vo, "add-admin"), "--cert %s" % cert) + def voms_ro_auth_clients_cmd(vo): return __voms_db_util_base_cmd(vo, "grant-read-only-access") - + + def voms_deploy_database_cmd(vo): return __voms_db_util_base_cmd(vo, "deploy") + def voms_undeploy_database_cmd(vo): return __voms_db_util_base_cmd(vo, "undeploy") + def voms_upgrade_database_cmd(vo): return __voms_db_util_base_cmd(vo, "upgrade") + def __voms_db_util_base_cmd(vo, command): return "%s %s --vo %s" % (VOMSDefaults.voms_db_util, command, vo) + def voms_version(): if __voms_version__ == "${pom.version": return "unset" return __voms_version__ + def voms_prefix(): if __voms_prefix__ == "${package.prefix}": return "/opt/voms" else: return __voms_prefix__ + def template_prefix(): - return os.path.join(voms_prefix(), "usr","share", "voms-admin","templates") + return os.path.join(voms_prefix(), "usr", "share", "voms-admin", "templates") + def admin_conf_dir(vo=None): if vo is None: @@ -84,178 +100,199 @@ def admin_conf_dir(vo=None): else: return os.path.join(voms_prefix(), "etc", "voms-admin", vo) + def core_conf_dir(vo=None): if vo is None: - return os.path.join(voms_prefix(), "etc","voms") + return os.path.join(voms_prefix(), "etc", "voms") else: - return os.path.join(voms_prefix(), "etc","voms", vo) + return os.path.join(voms_prefix(), "etc", "voms", vo) + def admin_db_properties_path(vo): return os.path.join(admin_conf_dir(vo), "database.properties") + def admin_service_properties_path(vo): return os.path.join(admin_conf_dir(vo), "service.properties") + def admin_service_endpoint_path(vo): return os.path.join(admin_conf_dir(vo), "service-endpoint") + def admin_logging_conf_path(vo): return os.path.join(admin_conf_dir(vo), "logback.xml") + def vomses_path(vo): return os.path.join(admin_conf_dir(vo), "vomses") + def lsc_path(vo): return os.path.join(admin_conf_dir(vo), "lsc") + def aup_path(vo): return os.path.join(admin_conf_dir(vo), "vo-aup.txt") + def voms_log_path(): - return os.path.join(voms_prefix(),"var", "log", "voms") + return os.path.join(voms_prefix(), "var", "log", "voms") + def voms_conf_path(vo): return os.path.join(core_conf_dir(), vo, "voms.conf") + def voms_pass_path(vo): return os.path.join(core_conf_dir(), vo, "voms.pass") + def voms_lib_dir(): - prefix=voms_prefix() - + prefix = voms_prefix() + plat = platform.machine() libdir = "lib" - + if plat == "x86_64": - ## FIXME: understand how this behaves in Debian + # FIXME: understand how this behaves in Debian libdir = "lib64" - - return os.path.join(prefix,"usr", libdir) + + return os.path.join(prefix, "usr", libdir, "voms") + class VOMSDefaults: db_props_template = os.path.join(template_prefix(), "database.properties") - service_props_template = os.path.join(template_prefix(),"service.properties") - voms_template = os.path.join(template_prefix(),"voms.conf") - - vo_aup_template = os.path.join(template_prefix(),"vo-aup.txt") + service_props_template = os.path.join( + template_prefix(), "service.properties") + voms_template = os.path.join(template_prefix(), "voms.conf") + + vo_aup_template = os.path.join(template_prefix(), "vo-aup.txt") logging_conf_template = os.path.join(template_prefix(), "logback.xml") - - voms_admin_war = os.path.join(voms_prefix(), "usr","share","webapps","voms-admin.war") - - voms_admin_libs = glob.glob(os.path.join(voms_prefix(),"var", "lib","voms-admin","lib")+"/*.jar") - voms_admin_classes = os.path.join(voms_prefix(),"var", "lib","voms-admin","tools") - voms_admin_jar = os.path.join(voms_prefix(), "usr", "share","java","voms-admin.jar") - - voms_db_util = os.path.join(voms_prefix(),"usr", "sbin","voms-db-util") - voms_mysql_util = os.path.join(voms_prefix(), "usr", "sbin", "voms-mysql-util") - + + voms_admin_war = os.path.join( + voms_prefix(), "usr", "share", "webapps", "voms-admin.war") + + voms_admin_libs = glob.glob(os.path.join( + voms_prefix(), "var", "lib", "voms-admin", "lib")+"/*.jar") + voms_admin_classes = os.path.join( + voms_prefix(), "var", "lib", "voms-admin", "tools") + voms_admin_jar = os.path.join( + voms_prefix(), "usr", "share", "java", "voms-admin.jar") + + voms_db_util = os.path.join(voms_prefix(), "usr", "sbin", "voms-db-util") + voms_mysql_util = os.path.join( + voms_prefix(), "usr", "sbin", "voms-mysql-util") + schema_deployer_class = "org.glite.security.voms.admin.persistence.deployer.SchemaDeployer" - + oracle_driver_class = "oracle.jdbc.driver.OracleDriver" oracle_dialect = "org.hibernate.dialect.Oracle9Dialect" - + mysql_driver_class = "org.gjt.mm.mysql.Driver" mysql_dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" - def parse_sysconfig(): - sysconfig_filename = os.path.join(voms_prefix(), + sysconfig_filename = os.path.join(voms_prefix(), "etc", "sysconfig", "voms-admin") - + helper = PropertyHelper(sysconfig_filename) return helper + def get_oracle_env(): sysconfig = parse_sysconfig() template_str = "LD_LIBRARY_PATH=$ORACLE_LIBRARY_PATH TNS_ADMIN=$TNS_ADMIN" template = string.Template(template_str) return template.substitute(sysconfig) - -class VOMSError(exceptions.RuntimeError): + + +class VOMSError(exceptions.RuntimeError): pass + class PropertyHelper(dict): empty_or_comment_lines = re.compile("^\\s*$|^#.*$") property_matcher = re.compile("^\\s*([^=\\s]+)=?\\s*(\\S.*)$") - - def __init__(self,filename): + def __init__(self, filename): self._filename = filename self._load_properties() - + def _load_properties(self): - f = open(self._filename,"r") + f = open(self._filename, "r") for l in f: if re.match(PropertyHelper.empty_or_comment_lines, l) is None: - m = re.search(PropertyHelper.property_matcher,l) + m = re.search(PropertyHelper.property_matcher, l) if m: - PropertyHelper.__setitem__(self,m.groups()[0],m.groups()[1]) + PropertyHelper.__setitem__( + self, m.groups()[0], m.groups()[1]) f.close() - + def save_properties(self): def helper(l): - m = re.search(PropertyHelper.property_matcher,l) + m = re.search(PropertyHelper.property_matcher, l) if m: - return re.sub("=.*$","=%s" % self[m.groups()[0]],l) + return re.sub("=.*$", "=%s" % self[m.groups()[0]], l) else: return l - - f = open(self._filename,"rw+") - lines = map(helper,f.readlines()) + + f = open(self._filename, "rw+") + lines = map(helper, f.readlines()) f.seek(0) f.writelines(lines) f.truncate() f.close() - - + class X509Helper: - def __init__(self,filename, openssl_cmd=None): - self.filename= filename + def __init__(self, filename, openssl_cmd=None): + self.filename = filename self.openssl_cmd = openssl_cmd self.parse() - + def parse(self): - + if self.openssl_cmd: openssl = self.openssl_cmd else: openssl = 'openssl' - + base_cmd = openssl+' x509 -in \'%s\' -noout ' % self.filename - - status,subject = commands.getstatusoutput(base_cmd+'-subject') + + status, subject = commands.getstatusoutput(base_cmd+'-subject') if status: - raise VOMSError, "Error invoking openssl: "+ subject - - status,issuer = commands.getstatusoutput(base_cmd+'-issuer') + raise VOMSError, "Error invoking openssl: " + subject + + status, issuer = commands.getstatusoutput(base_cmd+'-issuer') if status: - raise VOMSError, "Error invoking openssl: "+ issuer - - - status,email = commands.getstatusoutput(base_cmd+'-email') + raise VOMSError, "Error invoking openssl: " + issuer + + status, email = commands.getstatusoutput(base_cmd+'-email') if status: - raise VOMSError, "Error invoking openssl: "+ email - - self.subject = re.sub(r'^subject= ','',subject.strip()) - self.issuer = re.sub(r'^issuer= ','',issuer.strip()) - self.subject = re.sub(r'/(E|e|((E|e|)(mail|mailAddress|mailaddress|MAIL|MAILADDRESS)))=','/Email=',self.subject) - + raise VOMSError, "Error invoking openssl: " + email + + self.subject = re.sub(r'^subject= ', '', subject.strip()) + self.issuer = re.sub(r'^issuer= ', '', issuer.strip()) + self.subject = re.sub( + r'/(E|e|((E|e|)(mail|mailAddress|mailaddress|MAIL|MAILADDRESS)))=', '/Email=', self.subject) + # Handle emailAddress also in the CA DN (Bug #36490) - self.issuer = re.sub(r'/(E|e|((E|e|)(mail|mailAddress|mailaddress|MAIL|MAILADDRESS)))=','/Email=',self.issuer) - + self.issuer = re.sub( + r'/(E|e|((E|e|)(mail|mailAddress|mailaddress|MAIL|MAILADDRESS)))=', '/Email=', self.issuer) + # Handle also UID - self.subject = re.sub(r'/(UserId|USERID|userId|userid|uid|Uid)=','/UID=',self.subject) - + self.subject = re.sub( + r'/(UserId|USERID|userId|userid|uid|Uid)=', '/UID=', self.subject) + self.email = email.strip() - + # Check that only first email address is taken from the certificate, the openssl -email command # returns one address per line emails = email.splitlines(False) if len(emails) > 0: self.email = emails[0] - - + def __repr__(self): return 'Subject:%s\nIssuer:%s\nEmail:%s' % (self.subject, self.issuer, self.email) From 87fed382287bc8b5e3884b9c6b65da1702601cb1 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Sat, 29 Aug 2020 09:29:40 +0200 Subject: [PATCH 47/63] Bump versions for guava, commons-collections and mysql-connector --- pom.xml | 2 +- voms-admin-server/pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f0461442..2b1f065b 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ --> 1.1 2.11 - 21.0 + 29.0-jre var/log/voms-admin /code diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index bd8f0b58..cf6d66a0 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -290,7 +290,7 @@ commons-collections commons-collections - 3.2.1 + 3.2.2 @@ -332,7 +332,7 @@ mysql mysql-connector-java - 5.0.7 + 8.0.16 From 41862696d36ac79732d8932f5e799bd8b0ed3c65 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Sun, 30 Aug 2020 12:43:26 +0200 Subject: [PATCH 48/63] Fix mysql driver name --- voms-admin-server/resources/scripts/configure/voms_shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voms-admin-server/resources/scripts/configure/voms_shared.py b/voms-admin-server/resources/scripts/configure/voms_shared.py index ada71321..dc353a1c 100644 --- a/voms-admin-server/resources/scripts/configure/voms_shared.py +++ b/voms-admin-server/resources/scripts/configure/voms_shared.py @@ -189,7 +189,7 @@ class VOMSDefaults: oracle_driver_class = "oracle.jdbc.driver.OracleDriver" oracle_dialect = "org.hibernate.dialect.Oracle9Dialect" - mysql_driver_class = "org.gjt.mm.mysql.Driver" + mysql_driver_class = "com.mysql.cj.jdbc.Driver" mysql_dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" From 61fcbfdb195a018d219f2a176f26a43be6f87ccf Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 31 Aug 2020 09:58:38 +0200 Subject: [PATCH 49/63] Upgraded to struts 2.5.22 --- compose/assets/hr/fixture/participations.csv | 3 +- compose/docker-compose.yml | 4 +- voms-admin-server/pom.xml | 10 ++--- ...AttributeAuthoritySoapBindingSkeleton.java | 37 ++++++++------- .../integration/cern/HrDbExchangeError.java | 15 +++++++ .../cern/VoPersonNotFoundError.java | 15 +++++++ .../tools/CleanupTaskLogRecords.java | 15 +++++++ .../voms/admin/util/migration/MigrateVo.java | 3 +- .../voms/admin/view/actions/BaseAction.java | 5 ++- .../view/actions/apiv2/CreateUserAction.java | 2 +- .../view/actions/apiv2/SuspendUserAction.java | 31 ++++++++----- .../register/hr/HrRegisterActionSupport.java | 15 +++++++ .../register/hr/ResolveHrIdAction.java | 15 +++++++ .../AuthzExceptionInterceptor.java | 6 +-- .../JSONExceptionReportInterceptor.java | 3 +- .../JSONValidationReportInterceptor.java | 45 ++++++++++--------- .../view/preparers/acl/AddEntryPreparer.java | 33 +++++++------- .../view/preparers/acl/ManagePreparer.java | 18 ++++---- .../ListAttributeClassesPreparer.java | 19 ++++---- .../preparers/group/ListGroupPreparer.java | 19 ++++---- .../register/SelectManagerViewPreparer.java | 18 +++----- .../preparers/role/RoleDetailPreparer.java | 14 +++--- .../user/AddCertificatePreparer.java | 14 +++--- .../preparers/user/ListUsersPreparer.java | 13 +++--- .../preparers/user/UserDetailPreparer.java | 13 +++--- .../main/webapp/WEB-INF/classes/struts.xml | 4 +- .../WEB-INF/p/shared/dialog-template.jsp | 6 ++- .../src/main/webapp/WEB-INF/web.xml | 2 +- 28 files changed, 245 insertions(+), 152 deletions(-) diff --git a/compose/assets/hr/fixture/participations.csv b/compose/assets/hr/fixture/participations.csv index 7382545e..294fbcfe 100644 --- a/compose/assets/hr/fixture/participations.csv +++ b/compose/assets/hr/fixture/participations.csv @@ -1,4 +1,5 @@ experiment|institute|person_id|start_date|end_date TEST|000000|1|01-FEB-08| TEST|000002|2|01-FEB-08| -TEST|000001|3|01-FEB-08| +TEST|000001|3|01-FEB-08|01-FEB-09| +TEST|000001|3|01-FEB-10| diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index 4eeef922..8d52199a 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -7,7 +7,7 @@ volumes: services: trust: - image: indigoiam/trustanchors + image: indigoiam/trustanchors:latest environment: - FORCE_TRUST_ANCHORS_UPDATE=1 volumes: @@ -71,7 +71,7 @@ services: VOMS_DEBUG: y # Comment the following line to skip tarball installation - #VOMS_DEPLOY_TARBALL: y + VOMS_DEPLOY_TARBALL: y # VOMS_ADMIN_SERVER_PACKAGE_URL: http://ci-01.cnaf.infn.it/download/voms/versions/jenkins-release_voms_packages-13/sl6/x86_64/voms-admin-server-3.5.1-1.el6.centos.noarch.rpm # VOMS_ADMIN_SERVER_VERSION: 3.3.3 diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index cf6d66a0..f722e951 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -36,13 +36,13 @@ ${project.version} 2.0.2 - 2.3.37 - 2.0.1 - 3.7.1 + 2.5.22 + 2.5.2 + 4.0.3 5.2.17.Final 0.9.5.4 2.5.3 - 2.2.2 + 3.0.8 3.2 5.5.1 2.2 @@ -358,7 +358,7 @@ com.jgeppert.struts2.bootstrap struts2-bootstrap-plugin - ${struts.boostrap.plugin.version} + ${struts.bootstrap.plugin.version} diff --git a/voms-admin-server/src/main/java/it/infn/cnaf/voms/saml/axis_skeletons/AttributeAuthoritySoapBindingSkeleton.java b/voms-admin-server/src/main/java/it/infn/cnaf/voms/saml/axis_skeletons/AttributeAuthoritySoapBindingSkeleton.java index 6ecbeb29..a89fe3f5 100644 --- a/voms-admin-server/src/main/java/it/infn/cnaf/voms/saml/axis_skeletons/AttributeAuthoritySoapBindingSkeleton.java +++ b/voms-admin-server/src/main/java/it/infn/cnaf/voms/saml/axis_skeletons/AttributeAuthoritySoapBindingSkeleton.java @@ -22,9 +22,10 @@ package it.infn.cnaf.voms.saml.axis_skeletons; -public class AttributeAuthoritySoapBindingSkeleton implements - it.infn.cnaf.voms.saml.axis_skeletons.AttributeAuthorityPortType, - org.apache.axis.wsdl.Skeleton { +@SuppressWarnings({"serial", "rawtypes"}) +public class AttributeAuthoritySoapBindingSkeleton + implements it.infn.cnaf.voms.saml.axis_skeletons.AttributeAuthorityPortType, + org.apache.axis.wsdl.Skeleton { private it.infn.cnaf.voms.saml.axis_skeletons.AttributeAuthorityPortType impl; private static java.util.Map _myOperations = new java.util.Hashtable(); @@ -33,8 +34,7 @@ public class AttributeAuthoritySoapBindingSkeleton implements /** * Returns List of OperationDesc objects with this name */ - public static java.util.List getOperationDescByName( - java.lang.String methodName) { + public static java.util.List getOperationDescByName(java.lang.String methodName) { return (java.util.List) _myOperations.get(methodName); } @@ -51,17 +51,17 @@ public static java.util.Collection getOperationDescs() { org.apache.axis.description.OperationDesc _oper; org.apache.axis.description.FaultDesc _fault; org.apache.axis.description.ParameterDesc[] _params; - _params = new org.apache.axis.description.ParameterDesc[] { new org.apache.axis.description.ParameterDesc( - new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", - "AttributeQuery"), org.apache.axis.description.ParameterDesc.IN, - new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", - "AttributeQueryType"), org.opensaml.saml2.core.AttributeQuery.class, - false, false), }; - _oper = new org.apache.axis.description.OperationDesc("attributeQuery", - _params, new javax.xml.namespace.QName( - "urn:oasis:names:tc:SAML:2.0:protocol", "Response")); - _oper.setReturnType(new javax.xml.namespace.QName( - "urn:oasis:names:tc:SAML:2.0:protocol", "ResponseType")); + _params = new org.apache.axis.description.ParameterDesc[] { + new org.apache.axis.description.ParameterDesc( + new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", "AttributeQuery"), + org.apache.axis.description.ParameterDesc.IN, + new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", + "AttributeQueryType"), + org.opensaml.saml2.core.AttributeQuery.class, false, false),}; + _oper = new org.apache.axis.description.OperationDesc("attributeQuery", _params, + new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", "Response")); + _oper.setReturnType( + new javax.xml.namespace.QName("urn:oasis:names:tc:SAML:2.0:protocol", "ResponseType")); _oper.setElementQName(new javax.xml.namespace.QName("", "attributeQuery")); _oper.setSoapAction(""); _myOperationsList.add(_oper); @@ -77,14 +77,13 @@ public AttributeAuthoritySoapBindingSkeleton() { } public AttributeAuthoritySoapBindingSkeleton( - it.infn.cnaf.voms.saml.axis_skeletons.AttributeAuthorityPortType impl) { + it.infn.cnaf.voms.saml.axis_skeletons.AttributeAuthorityPortType impl) { this.impl = impl; } public org.opensaml.saml2.core.Response attributeQuery( - org.opensaml.saml2.core.AttributeQuery body) - throws java.rmi.RemoteException { + org.opensaml.saml2.core.AttributeQuery body) throws java.rmi.RemoteException { org.opensaml.saml2.core.Response ret = impl.attributeQuery(body); return ret; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java index 063b10e5..88848109 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbExchangeError.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.integration.cern; public class HrDbExchangeError extends HrDbError { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java index a258b384..772c0095 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/VoPersonNotFoundError.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.integration.cern; public class VoPersonNotFoundError extends HrDbExchangeError { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java index 828b4dc9..22802c50 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/tools/CleanupTaskLogRecords.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.persistence.tools; import static java.lang.Long.parseLong; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java index 38cebc8e..9125d15b 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/util/migration/MigrateVo.java @@ -44,6 +44,7 @@ import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.commons.lang3.StringUtils; +import org.apache.struts2.json.DefaultJSONWriter; import org.apache.struts2.json.JSONException; import org.apache.struts2.json.JSONPopulator; import org.apache.struts2.json.JSONReader; @@ -92,7 +93,7 @@ public class MigrateVo implements MigrateVoConstants, Runnable { Protocol vomsHttps; JSONReader jsonReader = new JSONReader(); - JSONWriter jsonWriter = new JSONWriter(); + JSONWriter jsonWriter = new DefaultJSONWriter(); JSONPopulator jsonPopulator = new JSONPopulator(); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/BaseAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/BaseAction.java index 4ed71e14..26036e1a 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/BaseAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/BaseAction.java @@ -40,9 +40,10 @@ import org.hibernate.Hibernate; import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.ValidationAware; +import com.opensymphony.xwork2.interceptor.ValidationAware; -public class BaseAction extends ActionSupport implements ValidationAware, RequestAware { +public class BaseAction extends ActionSupport + implements ValidationAware, RequestAware { /** * */ diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/CreateUserAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/CreateUserAction.java index f569e1cd..256ac3f2 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/CreateUserAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/CreateUserAction.java @@ -26,7 +26,7 @@ import org.glite.security.voms.admin.persistence.model.VOMSUser; import org.glite.security.voms.admin.view.actions.BaseAction; -import com.opensymphony.xwork2.ValidationAware; +import com.opensymphony.xwork2.interceptor.ValidationAware; import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; import com.opensymphony.xwork2.validator.annotations.ValidatorType; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/SuspendUserAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/SuspendUserAction.java index 3963c8ee..f4890e78 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/SuspendUserAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/apiv2/SuspendUserAction.java @@ -16,7 +16,9 @@ package org.glite.security.voms.admin.view.actions.apiv2; import java.util.Collection; +import java.util.regex.Pattern; +import org.apache.logging.log4j.util.Strings; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; @@ -25,14 +27,28 @@ import org.glite.security.voms.admin.persistence.model.VOMSUser.SuspensionReason; import org.glite.security.voms.admin.view.actions.BaseAction; -import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; -import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; -import com.opensymphony.xwork2.validator.annotations.ValidatorType; - @ParentPackage("json") @Results({ @Result(name = BaseAction.SUCCESS, type = "json") }) public class SuspendUserAction extends RestUserAction { + private static final Pattern REGEX = Pattern.compile("^[^<>&;]*$"); + + @Override + public void validate() { + + // Workaround for annotation validation not working anymore + // due to OGNL not finding the right value in the OGNL stack + + if (Strings.isBlank(suspensionReason)) { + addFieldError("suspensionReason", "Please provide a reason for the suspension."); + } else { + + if (!REGEX.matcher(suspensionReason).matches()) { + addFieldError("suspensionReason", "The reason contains illegal characters."); + } + + } + } /** * */ @@ -53,13 +69,8 @@ public String execute() throws Exception { return SUCCESS; } - @RequiredStringValidator(type = ValidatorType.FIELD, - message = "Please provide a reason for the suspension.") - @RegexFieldValidator(type = ValidatorType.FIELD, - message = "The reason contains illegal characters!", - regex = "^[^<>&;]*$") - public String getSuspensionReason() { + public String getSuspensionReason() { return suspensionReason; } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java index aed073ce..c31d09c4 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/HrRegisterActionSupport.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.view.actions.register.hr; import static java.util.Objects.isNull; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java index 598fc7f8..43033c49 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/actions/register/hr/ResolveHrIdAction.java @@ -1,3 +1,18 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.glite.security.voms.admin.view.actions.register.hr; import java.time.Instant; diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/AuthzExceptionInterceptor.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/AuthzExceptionInterceptor.java index 6c5089e1..5d2e48ad 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/AuthzExceptionInterceptor.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/AuthzExceptionInterceptor.java @@ -15,15 +15,15 @@ */ package org.glite.security.voms.admin.view.interceptors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.glite.security.voms.admin.error.VOMSAuthorizationException; import org.glite.security.voms.admin.view.actions.AuthorizationErrorAware; import org.glite.security.voms.admin.view.actions.BaseAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ValidationAware; import com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor; +import com.opensymphony.xwork2.interceptor.ValidationAware; public class AuthzExceptionInterceptor extends ExceptionMappingInterceptor { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONExceptionReportInterceptor.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONExceptionReportInterceptor.java index c7722721..543c4696 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONExceptionReportInterceptor.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONExceptionReportInterceptor.java @@ -18,7 +18,8 @@ import org.glite.security.voms.admin.error.VOMSAuthorizationException; import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ValidationAware; +import com.opensymphony.xwork2.interceptor.ValidationAware; + public class JSONExceptionReportInterceptor extends JSONValidationReportInterceptor { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONValidationReportInterceptor.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONValidationReportInterceptor.java index 11ec4f41..65b38209 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONValidationReportInterceptor.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/interceptors/JSONValidationReportInterceptor.java @@ -22,28 +22,30 @@ import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.json.DefaultJSONWriter; import org.apache.struts2.json.JSONException; -import org.apache.struts2.json.JSONUtil; +import org.apache.struts2.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ValidationAware; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; +import com.opensymphony.xwork2.interceptor.ValidationAware; public class JSONValidationReportInterceptor extends MethodFilterInterceptor { - public static final Logger log = LoggerFactory - .getLogger(JSONValidationReportInterceptor.class); + public static final Logger log = LoggerFactory.getLogger(JSONValidationReportInterceptor.class); /** - * - */ + * + */ private static final long serialVersionUID = 1L; private int validationFailedStatus = -1; + private final JSONWriter jsonWriter = new DefaultJSONWriter(); + /** * HTTP status that will be set in the response if validation fails * @@ -73,7 +75,7 @@ protected String doIntercept(ActionInvocation invocation) throws Exception { } protected boolean hasValidationErrors(ActionInvocation invocation) - throws IOException, JSONException { + throws IOException, JSONException { Object action = invocation.getAction(); if (action instanceof ValidationAware) { @@ -86,35 +88,35 @@ protected boolean hasValidationErrors(ActionInvocation invocation) } protected String generateJSON(ValidationAware validationAware, Throwable t) - throws IOException, JSONException { + throws IOException, JSONException { return generateJSON(validationAware, t, -1); } - + protected String generateJSON(ValidationAware validationAware, Throwable t, int statusCode) - throws IOException, JSONException { + throws IOException, JSONException { HttpServletResponse response = ServletActionContext.getResponse(); - + response.setContentType("application/json"); - - if (statusCode > 0){ - - response.sendError(statusCode, t.getMessage()); - + + if (statusCode > 0) { + + response.sendError(statusCode, t.getMessage()); + } else { if (validationFailedStatus >= 0) { response.setStatus(validationFailedStatus); } String responseContent = buildResponse(validationAware, t); - + response.getWriter().print(responseContent); - } - + } + return Action.NONE; } protected String buildResponse(ValidationAware validationAware, Throwable t) - throws JSONException { + throws JSONException { Map errors = new HashMap(); @@ -132,7 +134,8 @@ protected String buildResponse(ValidationAware validationAware, Throwable t) if (validationAware.hasActionMessages()) errors.put("messages", validationAware.getActionMessages()); - return JSONUtil.serialize(errors); + + return jsonWriter.write(errors); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/AddEntryPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/AddEntryPreparer.java index 3485a935..85d42c2e 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/AddEntryPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/AddEntryPreparer.java @@ -16,11 +16,11 @@ package org.glite.security.voms.admin.view.preparers.acl; import java.util.List; +import java.util.Map; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.operations.groups.ListGroupsOperation; import org.glite.security.voms.admin.operations.roles.ListRolesOperation; import org.glite.security.voms.admin.operations.users.ListUsersOperation; @@ -31,26 +31,23 @@ import org.glite.security.voms.admin.persistence.model.VOMSRole; import org.glite.security.voms.admin.persistence.model.VOMSUser; -public class AddEntryPreparer extends ViewPreparerSupport { +public class AddEntryPreparer implements ViewPreparer { + @SuppressWarnings("unchecked") @Override - public void execute(TilesRequestContext tilesContext, - AttributeContext attributeContext) throws PreparerException { + public void execute(Request request, AttributeContext attributeContext) { - List groups = (List) ListGroupsOperation.instance() - .execute(); - List roles = (List) ListRolesOperation.instance() - .execute(); - List users = (List) ListUsersOperation.instance() - .execute(); + List groups = (List) ListGroupsOperation.instance().execute(); + List roles = (List) ListRolesOperation.instance().execute(); + List users = (List) ListUsersOperation.instance().execute(); List cas = (List) VOMSCADAO.instance().getValid(); - tilesContext.getRequestScope().put("voCertificates", - CertificateDAO.instance().getAll()); - tilesContext.getRequestScope().put("voUsers", users); - tilesContext.getRequestScope().put("voGroups", groups); - tilesContext.getRequestScope().put("voRoles", roles); - tilesContext.getRequestScope().put("voCAs", cas); + Map context = request.getContext(Request.REQUEST_SCOPE); + context.put("voCertificates", CertificateDAO.instance().getAll()); + context.put("voUsers", users); + context.put("voGroups", groups); + context.put("voRoles", roles); + context.put("voCAs", cas); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/ManagePreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/ManagePreparer.java index 61337035..42ae0639 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/ManagePreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/acl/ManagePreparer.java @@ -15,24 +15,25 @@ */ package org.glite.security.voms.admin.view.preparers.acl; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.Collections; import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.error.VOMSAuthorizationException; import org.glite.security.voms.admin.operations.groups.ListGroupsOperation; import org.glite.security.voms.admin.operations.roles.ListRolesOperation; import org.glite.security.voms.admin.persistence.model.VOMSGroup; import org.glite.security.voms.admin.persistence.model.VOMSRole; -public class ManagePreparer extends ViewPreparerSupport { +public class ManagePreparer implements ViewPreparer { + @SuppressWarnings("unchecked") @Override - public void execute(TilesRequestContext tilesContext, - AttributeContext attributeContext) throws PreparerException { + public void execute(Request tilesContext, AttributeContext attributeContext) { List groups = Collections.EMPTY_LIST; List roles = Collections.EMPTY_LIST; @@ -47,8 +48,7 @@ public void execute(TilesRequestContext tilesContext, // swallow authorization exception } - tilesContext.getRequestScope().put("voGroups", groups); - tilesContext.getRequestScope().put("voRoles", roles); - + tilesContext.getContext(REQUEST_SCOPE).put("voGroups", groups); + tilesContext.getContext(REQUEST_SCOPE).put("voRoles", roles); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/attribute/ListAttributeClassesPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/attribute/ListAttributeClassesPreparer.java index 2751a3ac..e7f08180 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/attribute/ListAttributeClassesPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/attribute/ListAttributeClassesPreparer.java @@ -15,25 +15,26 @@ */ package org.glite.security.voms.admin.view.preparers.attribute; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.operations.attributes.ListAttributeDescriptionsOperation; import org.glite.security.voms.admin.persistence.model.attribute.VOMSAttributeDescription; -public class ListAttributeClassesPreparer extends ViewPreparerSupport { +public class ListAttributeClassesPreparer implements ViewPreparer { @Override - public void execute(TilesRequestContext tilesContext, - AttributeContext attributeContext) throws PreparerException { + public void execute(Request request, AttributeContext attributeContext) { - List attributeClasses = (List) ListAttributeDescriptionsOperation - .instance().execute(); + @SuppressWarnings("unchecked") + List attributeClasses = + (List) ListAttributeDescriptionsOperation.instance().execute(); - tilesContext.getRequestScope().put("attributeClasses", attributeClasses); + request.getContext(REQUEST_SCOPE).put("attributeClasses", attributeClasses); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/group/ListGroupPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/group/ListGroupPreparer.java index b28d2d8f..e3565dcb 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/group/ListGroupPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/group/ListGroupPreparer.java @@ -15,25 +15,24 @@ */ package org.glite.security.voms.admin.view.preparers.group; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.operations.groups.ListGroupsOperation; import org.glite.security.voms.admin.persistence.model.VOMSGroup; -public class ListGroupPreparer extends ViewPreparerSupport { - - public void execute(TilesRequestContext requestContext, - AttributeContext attributeContext) throws PreparerException { +public class ListGroupPreparer implements ViewPreparer { + @Override + public void execute(Request tilesContext, AttributeContext attributeContext) { @SuppressWarnings("unchecked") - List groups = (List) ListGroupsOperation.instance() - .execute(); + List groups = (List) ListGroupsOperation.instance().execute(); - requestContext.getRequestScope().put("voGroups", groups); + tilesContext.getContext(REQUEST_SCOPE).put("voGroups", groups); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/register/SelectManagerViewPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/register/SelectManagerViewPreparer.java index 020deca3..f2999a9a 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/register/SelectManagerViewPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/register/SelectManagerViewPreparer.java @@ -18,23 +18,17 @@ import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.persistence.dao.generic.DAOFactory; import org.glite.security.voms.admin.persistence.model.GroupManager; -public class SelectManagerViewPreparer extends ViewPreparerSupport { +public class SelectManagerViewPreparer implements ViewPreparer { @Override - public void execute(TilesRequestContext tilesContext, - AttributeContext attributeContext) throws PreparerException { - - List managers = DAOFactory.instance().getGroupManagerDAO() - .findAll(); - - tilesContext.getRequestScope().put("groupManagers", managers); - + public void execute(Request tilesContext, AttributeContext attributeContext) { + List managers = DAOFactory.instance().getGroupManagerDAO().findAll(); + tilesContext.getContext(Request.REQUEST_SCOPE).put("groupManagers", managers); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/role/RoleDetailPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/role/RoleDetailPreparer.java index c4561405..b55e8fd4 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/role/RoleDetailPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/role/RoleDetailPreparer.java @@ -15,24 +15,28 @@ */ package org.glite.security.voms.admin.view.preparers.role; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.operations.groups.ListGroupsOperation; import org.glite.security.voms.admin.persistence.model.VOMSGroup; -public class RoleDetailPreparer extends ViewPreparerSupport { +public class RoleDetailPreparer implements ViewPreparer { @Override - public void execute(TilesRequestContext tilesContext, + public void execute(Request tilesContext, AttributeContext attributeContext) throws PreparerException { + @SuppressWarnings("unchecked") List groups = (List) ListGroupsOperation.instance() .execute(); - tilesContext.getRequestScope().put("voGroups", groups); + + tilesContext.getContext(REQUEST_SCOPE).put("voGroups", groups); } } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/AddCertificatePreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/AddCertificatePreparer.java index f7964e32..8cea8fbc 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/AddCertificatePreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/AddCertificatePreparer.java @@ -15,23 +15,23 @@ */ package org.glite.security.voms.admin.view.preparers.user; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; -import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.persistence.dao.VOMSCADAO; import org.glite.security.voms.admin.persistence.model.VOMSCA; -public class AddCertificatePreparer extends ViewPreparerSupport { +public class AddCertificatePreparer implements ViewPreparer { @Override - public void execute(TilesRequestContext tilesContext, - AttributeContext attributeContext) throws PreparerException { + public void execute(Request request, AttributeContext attributeContext) { List trustedCas = VOMSCADAO.instance().getValid(); - tilesContext.getRequestScope().put("trustedCas", trustedCas); + request.getContext(REQUEST_SCOPE).put("trustedCas", trustedCas); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/ListUsersPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/ListUsersPreparer.java index 538aac64..deb78a0d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/ListUsersPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/ListUsersPreparer.java @@ -18,24 +18,23 @@ import java.util.Collections; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; import org.apache.tiles.preparer.PreparerException; import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.error.VOMSAuthorizationException; import org.glite.security.voms.admin.operations.groups.ListGroupsOperation; import org.glite.security.voms.admin.operations.roles.ListRolesOperation; import org.glite.security.voms.admin.persistence.model.VOMSGroup; import org.glite.security.voms.admin.persistence.model.VOMSRole; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ListUsersPreparer implements ViewPreparer { private static Logger log = LoggerFactory.getLogger(ListUsersPreparer.class); - public void execute(TilesRequestContext context, - AttributeContext attributeContext) throws PreparerException { + public void execute(Request request, AttributeContext attributeContext) throws PreparerException { List groups; List roles; @@ -55,8 +54,8 @@ public void execute(TilesRequestContext context, roles = Collections.EMPTY_LIST; } - context.getRequestScope().put("voGroups", groups); - context.getRequestScope().put("voRoles", roles); + request.getContext(Request.REQUEST_SCOPE).put("voGroups", groups); + request.getContext(Request.REQUEST_SCOPE).put("voRoles", roles); } diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/UserDetailPreparer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/UserDetailPreparer.java index a07a1b4c..2ed4d94a 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/UserDetailPreparer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/view/preparers/user/UserDetailPreparer.java @@ -15,24 +15,27 @@ */ package org.glite.security.voms.admin.view.preparers.user; +import static org.apache.tiles.request.Request.REQUEST_SCOPE; + import java.util.List; import org.apache.tiles.AttributeContext; -import org.apache.tiles.context.TilesRequestContext; import org.apache.tiles.preparer.PreparerException; -import org.apache.tiles.preparer.ViewPreparerSupport; +import org.apache.tiles.preparer.ViewPreparer; +import org.apache.tiles.request.Request; import org.glite.security.voms.admin.persistence.dao.VOMSAttributeDAO; import org.glite.security.voms.admin.persistence.model.attribute.VOMSAttributeDescription; -public class UserDetailPreparer extends ViewPreparerSupport { +public class UserDetailPreparer implements ViewPreparer { - public void execute(TilesRequestContext context, + public void execute(Request context, AttributeContext attributeContext) throws PreparerException { + @SuppressWarnings("unchecked") List attributeClasses = VOMSAttributeDAO .instance().getAllAttributeDescriptions(); - context.getRequestScope().put("attributeClasses", attributeClasses); + context.getContext(REQUEST_SCOPE).put("attributeClasses", attributeClasses); } diff --git a/voms-admin-server/src/main/webapp/WEB-INF/classes/struts.xml b/voms-admin-server/src/main/webapp/WEB-INF/classes/struts.xml index 8b1b8d5e..171e96fe 100644 --- a/voms-admin-server/src/main/webapp/WEB-INF/classes/struts.xml +++ b/voms-admin-server/src/main/webapp/WEB-INF/classes/struts.xml @@ -17,8 +17,8 @@ --> + "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" + "http://struts.apache.org/dtds/struts-2.5.dtd"> - - - @@ -233,12 +230,6 @@ Built on Jun 14, 2005 (09:15:57 EDT)--> - - - - - - @@ -361,16 +352,6 @@ Built on Jun 14, 2005 (09:15:57 EDT)--> - - - - - - - - - - @@ -651,30 +632,6 @@ Built on Jun 14, 2005 (09:15:57 EDT)--> - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/service/VomsAttributesService.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/service/VomsAttributesService.java index 474f40d1..8e46a823 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/service/VomsAttributesService.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/service/VomsAttributesService.java @@ -20,8 +20,6 @@ import java.util.List; import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.glite.security.voms.User; import org.glite.security.voms.VOMSException; import org.glite.security.voms.admin.error.UnimplementedFeatureException; @@ -52,6 +50,8 @@ import org.glite.security.voms.service.attributes.AttributeClass; import org.glite.security.voms.service.attributes.AttributeValue; import org.glite.security.voms.service.attributes.VOMSAttributes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class VomsAttributesService implements VOMSAttributes { @@ -145,24 +145,6 @@ public void deleteAttributeClass(String name) throws RemoteException, } - public void deleteAttributeClass(AttributeClass attributeClass) - throws RemoteException, VOMSException { - - log.info("deleteAttributeClass(" - + StringUtils.join(new Object[] { attributeClass }, ',') + ");"); - - try { - - DeleteAttributeDescriptionOperation.instance(attributeClass.getName()) - .execute(); - - } catch (RuntimeException e) { - - ServiceExceptionHelper.handleServiceException(log, e); - throw e; - } - } - public void deleteGroupAttribute(String groupName, String attributeName) throws RemoteException, VOMSException { From 305a36531f482a326328581f5e83f3b40a5f73f2 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 31 Aug 2020 17:32:31 +0200 Subject: [PATCH 51/63] Fix inconsistent remove certificate behaviour Remove certificate was not working when invoked from the SOAP API. Debugging has shown that the PersistentSet used by hibernate works differently when the collection is initialized for a delete certificate operation coming from struts (i.e., from voms-admin web UI) than when the call comes from the SOAP API (i.e., the axis web service). Removing the FETCH_EAGER annotation on the collection seems to solve the problem locally, even though I have not understood why. Issue: https://issues.infn.it/jira/browse/VOMS-874 --- .../users/RemoveUserCertificateOperation.java | 4 +- .../admin/persistence/dao/VOMSUserDAO.java | 16 ++-- .../admin/persistence/model/Certificate.java | 80 +++++++++++++------ .../voms/admin/persistence/model/VOMSCA.java | 45 +++++------ .../admin/persistence/model/VOMSUser.java | 37 +++++---- 5 files changed, 103 insertions(+), 79 deletions(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/RemoveUserCertificateOperation.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/RemoveUserCertificateOperation.java index 3c795130..785fef1a 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/RemoveUserCertificateOperation.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/operations/users/RemoveUserCertificateOperation.java @@ -103,8 +103,8 @@ protected Object doExecute() { } VOMSUser u = cert.getUser(); - VOMSUserDAO.instance() - .deleteCertificate(cert); + + VOMSUserDAO.instance().deleteCertificate(u, cert); EventManager.instance() .dispatch(new UserCertificateRemoved(u, cert)); diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java index bb0f2bcb..afcdd769 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/dao/VOMSUserDAO.java @@ -88,10 +88,10 @@ public static VOMSUserDAO instance() { private VOMSUserDAO() { } - - + + public void deleteTasks(VOMSUser user) { - + String deleteTLRs = "delete from task_log_record where task_id in ( select t.task_id from " + "task t, usr u where t.usr_id = u.userid and u.userid = :userId )"; HibernateFactory.getSession() @@ -111,7 +111,7 @@ public void deleteTasks(VOMSUser user) { .createSQLQuery(deleteTasks) .setLong("userId", user.getId()) .executeUpdate(); - + } public void requestAUPReacceptance(VOMSUser user, AUP aup) { @@ -242,7 +242,7 @@ public ScrollableResults findUsersExpiredSinceDays(int numberOfDays) { Query q = HibernateFactory.getSession().createQuery(queryString); q.setDate("then", Date.from(then)); - + q.setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY); return q.scroll(); @@ -695,7 +695,7 @@ public VOMSUser delete(VOMSUser u) { u.getAttributes().clear(); u.getAupAcceptanceRecords().clear(); u.getPersonalInformations().clear(); - + u.getTasks().clear(); HibernateFactory.getSession().delete(u); @@ -747,7 +747,9 @@ public void deleteCertificate(VOMSUser u, Certificate cert) { if (u.getCertificates().size() == 1 && u.hasCertificate(cert)) throw new VOMSException("User has only one certificate registered, so it cannot be removed!"); - if (!u.getCertificates().remove(cert)) { + boolean removed = u.removeCertificate(cert); + + if (!removed) { // This should never happen throw new VOMSDatabaseException( "Inconsistent database! It was not possible to remove certificate '" + cert diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/Certificate.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/Certificate.java index ac711ce8..c0101fe2 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/Certificate.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/Certificate.java @@ -33,8 +33,6 @@ import javax.persistence.Transient; import org.apache.commons.lang.builder.CompareToBuilder; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; import org.glite.security.voms.admin.persistence.model.VOMSUser.SuspensionReason; import org.hibernate.annotations.NaturalId; @@ -147,33 +145,65 @@ public void setSuspended(boolean suspended) { this.suspended = suspended; } - public boolean equals(Object other) { - if (this == other) - return true; - - if (other == null) - return false; - - if (!(other instanceof Certificate)) - return false; - - Certificate that = (Certificate) other; - - EqualsBuilder builder = new EqualsBuilder(); - builder.append(getSubjectString(), that.getSubjectString()).append(getCa(), - that.getCa()); - - return builder.isEquals(); - - } + // public boolean equals(Object other) { + // + // if (this == other) + // return true; + // + // if (other == null) + // return false; + // + // if (!(other instanceof Certificate)) + // return false; + // + // Certificate that = (Certificate) other; + // + // EqualsBuilder builder = new EqualsBuilder(); + // builder.append(getSubjectString(), that.getSubjectString()).append(getCa(), + // that.getCa()); + // + // return builder.isEquals(); + // + // } + // + // public int hashCode() { + // + // HashCodeBuilder builder = new HashCodeBuilder(7, 37); + // builder.append(getSubjectString()).append(getCa()); + // + // return builder.toHashCode(); + // } + @Override public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((ca == null) ? 0 : ca.hashCode()); + result = prime * result + ((subjectString == null) ? 0 : subjectString.hashCode()); + return result; + } - HashCodeBuilder builder = new HashCodeBuilder(7, 37); - builder.append(getSubjectString()).append(getCa()); - - return builder.toHashCode(); + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Certificate other = (Certificate) obj; + if (ca == null) { + if (other.ca != null) + return false; + } else if (!ca.equals(other.ca)) + return false; + if (subjectString == null) { + if (other.subjectString != null) + return false; + } else if (!subjectString.equals(other.subjectString)) + return false; + return true; } public VOMSUser getUser() { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSCA.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSCA.java index 5ddb7089..bd57c850 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSCA.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSCA.java @@ -134,36 +134,29 @@ public String toString() { return subjectString; } - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object other) { + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((subjectString == null) ? 0 : subjectString.hashCode()); + return result; + } - if (this == other) + @Override + public boolean equals(Object obj) { + if (this == obj) return true; - - if (!(other instanceof VOMSCA)) + if (obj == null) return false; - - if (other == null) + if (getClass() != obj.getClass()) return false; - - final VOMSCA that = (VOMSCA) other; - return (getSubjectString().equals(that.getSubjectString())); - - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - - return subjectString.hashCode(); - + VOMSCA other = (VOMSCA) obj; + if (subjectString == null) { + if (other.subjectString != null) + return false; + } else if (!subjectString.equals(other.subjectString)) + return false; + return true; } public String getShortName() { diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java index 3a442a2b..e518829d 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/model/VOMSUser.java @@ -37,7 +37,6 @@ import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; -import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -50,7 +49,6 @@ import org.apache.commons.lang.builder.ToStringBuilder; import org.glite.security.voms.User; import org.glite.security.voms.admin.apiv2.VOMSUserJSON; -import org.glite.security.voms.admin.error.NotFoundException; import org.glite.security.voms.admin.error.NullArgumentException; import org.glite.security.voms.admin.error.VOMSSyntaxException; import org.glite.security.voms.admin.persistence.HibernateFactory; @@ -164,32 +162,29 @@ public VOMSUser() { /** Generic attributes mapping **/ @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) - Set attributes = new HashSet(); + Set attributes = new HashSet<>(); /** Membership mappings **/ @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) @SortNatural - Set mappings = new TreeSet(); + Set mappings = new TreeSet<>(); /** User certificates **/ - @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", fetch = FetchType.EAGER) - @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) - Set certificates = new HashSet(); + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) + Set certificates = new HashSet<>(); /** AUP acceptance records **/ - @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user") - @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) - Set aupAcceptanceRecords = new HashSet(); + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) + Set aupAcceptanceRecords = new HashSet<>(); /** Assigned tasks **/ - @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", fetch = FetchType.EAGER) - @org.hibernate.annotations.Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) - Set tasks = new HashSet(); + @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "user", orphanRemoval = true) + Set tasks = new HashSet<>(); /** Personal information set **/ // FIXME: currently ignored by configuration @Transient - Set personalInformations = new HashSet(); + Set personalInformations = new HashSet<>(); @Column(name = "orgdb_id", nullable = true) Long orgDbId; @@ -764,14 +759,18 @@ public List getCertificatesBySubject(String subject) { return result; } - public void removeCertificate(Certificate cert) { + public boolean removeCertificate(Certificate cert) { - if (!hasCertificate(cert)) - throw new NotFoundException( - "Certificate '" + cert + "' is not bound to user '" + this + "'."); + if (!hasCertificate(cert)) { + return false; + } - getCertificates().remove(cert); + boolean removed = getCertificates().remove(cert); + if (removed) { + cert.setUser(null); + } + return removed; } public String getAddress() { From ea8ab1e651c944390b61b004ef69b10738a88018 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 2 Sep 2020 07:05:23 +0200 Subject: [PATCH 52/63] Add support for mysql db url parameters Required by MySQL v.8 driver --- compose/docker-compose.yml | 10 +- .../scripts/configure/voms_configure.py | 478 +++++++++++------- 2 files changed, 314 insertions(+), 174 deletions(-) diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index 8d52199a..015f4f3e 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -62,7 +62,7 @@ services: environment: # This is the VOMS Admin configuration # - VOMS_VO_COUNT: 1 # 0 creates 1 VO, 1 two VOs, ... + VOMS_VO_COUNT: 0 # 0 creates 1 VO, 1 two VOs, ... VOMS_HOSTNAME: dev.local.io MAILHOST: mail MYSQL_ROOT_PASSWORD: pwd @@ -76,15 +76,15 @@ services: # VOMS_ADMIN_SERVER_PACKAGE_URL: http://ci-01.cnaf.infn.it/download/voms/versions/jenkins-release_voms_packages-13/sl6/x86_64/voms-admin-server-3.5.1-1.el6.centos.noarch.rpm # VOMS_ADMIN_SERVER_VERSION: 3.3.3 # VOMS_DEBUG_SUSPEND: y - VOMS_PRE_CONFIGURE: y + # VOMS_PRE_CONFIGURE: y # VOMS_SKIP_CONFIGURE: y VOMS_SKIP_JAVA_SETUP: y # VOMS_UPGRADE_DB: y - #VOMS_LOAD_DB_DUMP: y - VOMS_DEV_MODE: y + # VOMS_LOAD_DB_DUMP: y + # VOMS_DEV_MODE: y - VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check + VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check --dburlparams useSSL=false&serverTimezone=Europe/Rome VOMS_ARGS: --war /code/voms-admin-server/target/voms-admin.war # ENABLE_YOURKIT: y diff --git a/voms-admin-server/resources/scripts/configure/voms_configure.py b/voms-admin-server/resources/scripts/configure/voms_configure.py index 60e23c01..7ae10355 100644 --- a/voms-admin-server/resources/scripts/configure/voms_configure.py +++ b/voms-admin-server/resources/scripts/configure/voms_configure.py @@ -39,11 +39,10 @@ import random +MYSQL = "mysql" +ORACLE = "oracle" -MYSQL="mysql" -ORACLE="oracle" - -usage="""%prog command [options] +usage = """%prog command [options] Commands: install: installs or reconfigures a VO @@ -61,6 +60,7 @@ VOMS_CERT = "/etc/grid-security/vomscert.pem" VOMS_KEY = "/etc/grid-security/vomskey.pem" + def execute_cmd(cmd, error_msg=None): status = os.system(cmd) @@ -71,55 +71,78 @@ def execute_cmd(cmd, error_msg=None): else: error_and_exit(error_msg) + def backup_dir_contents(d): logger.debug("Backing up contents for directory: %s", d) - backup_filez = glob.glob(os.path.join(d,"*_backup_*")) + backup_filez = glob.glob(os.path.join(d, "*_backup_*")) - ## Remove backup filez + # Remove backup filez for f in backup_filez: - ## Don't remove backup directories potentially created by the user + # Don't remove backup directories potentially created by the user if not os.path.isdir(f): os.remove(f) - filez = glob.glob(os.path.join(d,"*")) - backup_date = time.strftime("%d-%m-%Y_%H-%M-%S",time.gmtime()) + filez = glob.glob(os.path.join(d, "*")) + backup_date = time.strftime("%d-%m-%Y_%H-%M-%S", time.gmtime()) for f in filez: os.rename(f, f+"_backup_"+backup_date) -def check_args_and_options(options,args): + +def check_args_and_options(options, args): if len(args) != 1 or args[0] not in commands: - error_and_exit("Please specify a single command among the following:\n\t%s" % "\n\t".join(commands)) + error_and_exit( + "Please specify a single command among the following:\n\t%s" % "\n\t".join(commands)) + def setup_cl_options(): - ## Base options - parser.add_option("--vo", dest="vo", help="the VO being configured", metavar="VO") - parser.add_option("--config-owner", dest="config_owner", help="the USER that will own configuration files", metavar="USER", default="voms") - parser.add_option("--verbose", dest="verbose", action="store_true", help="Be verbose.", default=False) - parser.add_option("--dry-run", dest="dry_run", action="store_true", help="Dry run execution. No files are touched.", default=False) - - parser.add_option("--hostname", dest="hostname", help="the VOMS services HOSTNAME", metavar="HOSTNAME", default=socket.gethostname()) - - ## Certificate and trust anchors (used for both voms and voms-admin services) - parser.add_option("--cert", dest="cert", help="the certificate CERT used to run the VOMS services", metavar="CERT", default="/etc/grid-security/hostcert.pem") - parser.add_option("--key", dest="key", help="the private key used to run the VOMS services", metavar="KEY", default="/etc/grid-security/hostkey.pem") - parser.add_option("--trust-dir", dest="trust_dir", help="The directory where CA certificates are stored", metavar="DIR", default="/etc/grid-security/certificates") - parser.add_option("--trust-refresh-period", type="int", dest="trust_refresh_period", help="How ofter CAs are refreshed from the filesystem (in seconds).", metavar="SECS", default=3600) - - parser.add_option("--skip-voms-core", dest="skip_voms_core", action="store_true", help="Skips VOMS core configuration", default=False) - parser.add_option("--skip-voms-admin", dest="skip_voms_admin", action="store_true", help="Skips VOMS admin configuration", default=False) - parser.add_option("--skip-database", dest="skip_database", action="store_true", help="Skips database operations", default=False) - parser.add_option("--deploy-database", dest="deploy_database", action="store_true", help="Deploys the database for the VO being configured, if not present", default=True) - parser.add_option("--undeploy-database", dest="undeploy_database", action="store_true", help="Undeploys the database for the VO being removed", default=False) + # Base options + parser.add_option("--vo", dest="vo", + help="the VO being configured", metavar="VO") + parser.add_option("--config-owner", dest="config_owner", + help="the USER that will own configuration files", metavar="USER", default="voms") + parser.add_option("--verbose", dest="verbose", + action="store_true", help="Be verbose.", default=False) + parser.add_option("--dry-run", dest="dry_run", action="store_true", + help="Dry run execution. No files are touched.", default=False) + + parser.add_option("--hostname", dest="hostname", help="the VOMS services HOSTNAME", + metavar="HOSTNAME", default=socket.gethostname()) + + # Certificate and trust anchors (used for both voms and voms-admin services) + parser.add_option("--cert", dest="cert", help="the certificate CERT used to run the VOMS services", + metavar="CERT", default="/etc/grid-security/hostcert.pem") + parser.add_option("--key", dest="key", help="the private key used to run the VOMS services", + metavar="KEY", default="/etc/grid-security/hostkey.pem") + parser.add_option("--trust-dir", dest="trust_dir", help="The directory where CA certificates are stored", + metavar="DIR", default="/etc/grid-security/certificates") + parser.add_option("--trust-refresh-period", type="int", dest="trust_refresh_period", + help="How ofter CAs are refreshed from the filesystem (in seconds).", metavar="SECS", default=3600) + + parser.add_option("--skip-voms-core", dest="skip_voms_core", + action="store_true", help="Skips VOMS core configuration", default=False) + parser.add_option("--skip-voms-admin", dest="skip_voms_admin", + action="store_true", help="Skips VOMS admin configuration", default=False) + parser.add_option("--skip-database", dest="skip_database", + action="store_true", help="Skips database operations", default=False) + parser.add_option("--deploy-database", dest="deploy_database", action="store_true", + help="Deploys the database for the VO being configured, if not present", default=True) + parser.add_option("--undeploy-database", dest="undeploy_database", action="store_true", + help="Undeploys the database for the VO being removed", default=False) # Other base options - parser.add_option("--openssl", dest="openssl", help="the PATH to the openssl command", metavar="PATH", default="openssl") - - ## Admin service options - admin_opt_group = OptionGroup(parser, "VOMS admin options", "These options drive the basic configuration of the VOMS admin service.") - admin_opt_group.add_option("--admin-port", dest="admin_port", type="int", help="the PORT on which the admin service will bind", metavar="PORT", default=8443) - admin_opt_group.add_option("--admin-cert", dest="admin_cert", help="Grants CERT full administrator privileges in the VO", metavar="CERT") - admin_opt_group.add_option("--read-only", dest="read_only", action="store_true", help="Sets the VOMS admin service as read-only", default=False) + parser.add_option("--openssl", dest="openssl", + help="the PATH to the openssl command", metavar="PATH", default="openssl") + + # Admin service options + admin_opt_group = OptionGroup( + parser, "VOMS admin options", "These options drive the basic configuration of the VOMS admin service.") + admin_opt_group.add_option("--admin-port", dest="admin_port", type="int", + help="the PORT on which the admin service will bind", metavar="PORT", default=8443) + admin_opt_group.add_option("--admin-cert", dest="admin_cert", + help="Grants CERT full administrator privileges in the VO", metavar="CERT") + admin_opt_group.add_option("--read-only", dest="read_only", action="store_true", + help="Sets the VOMS admin service as read-only", default=False) admin_opt_group.add_option("--disable-ro-access-for-authenticated-clients", dest="read_only_auth_clients", action="store_false", @@ -132,7 +155,6 @@ def setup_cl_options(): help="Skips the check on the certificate issuer when authenticating VOMS Admin clients", default=False) - admin_opt_group.add_option("--disable-permission-cache", dest="permission_cache_disable", action="store_true", @@ -141,23 +163,28 @@ def setup_cl_options(): parser.add_option_group(admin_opt_group) - - ## DB options - db_opt_group = OptionGroup(parser, "Database configuration options", "These options configure VOMS database access") - db_opt_group.add_option("--dbtype", dest="dbtype", help="The database TYPE (mysql or oracle)", metavar="TYPE", default=MYSQL) - db_opt_group.add_option("--dbname", dest="dbname", help="Sets the VOMS database name to DBNAME", metavar="DBNAME") - db_opt_group.add_option("--dbusername", dest="dbusername", help="Sets the VOMS MySQL username to be created as USER", metavar="USER") - db_opt_group.add_option("--dbpassword", dest="dbpassword", help="Sets the VOMS MySQL password for the user to be created as PWD", metavar="PWD") + # DB options + db_opt_group = OptionGroup( + parser, "Database configuration options", "These options configure VOMS database access") + db_opt_group.add_option("--dbtype", dest="dbtype", + help="The database TYPE (mysql or oracle)", metavar="TYPE", default=MYSQL) + db_opt_group.add_option("--dbname", dest="dbname", + help="Sets the VOMS database name to DBNAME", metavar="DBNAME") + db_opt_group.add_option("--dbusername", dest="dbusername", + help="Sets the VOMS MySQL username to be created as USER", metavar="USER") + db_opt_group.add_option("--dbpassword", dest="dbpassword", + help="Sets the VOMS MySQL password for the user to be created as PWD", metavar="PWD") parser.add_option_group(db_opt_group) - ## Connection pool options - conn_pool_opt_group = OptionGroup(parser, "Database connection pool options", "These options configure the voms admin service database connection pool") + # Connection pool options + conn_pool_opt_group = OptionGroup(parser, "Database connection pool options", + "These options configure the voms admin service database connection pool") conn_pool_opt_group.add_option("--c3p0-acquire-increment", - type='int', - dest="c3p0_acquire_increment", - help="Sets the number of new connections that are acquired from the database connection pool is exausted.", - metavar="NUM", - default=1) + type='int', + dest="c3p0_acquire_increment", + help="Sets the number of new connections that are acquired from the database connection pool is exausted.", + metavar="NUM", + default=1) conn_pool_opt_group.add_option("--c3p0-idle-test-period", type='int', @@ -196,49 +223,76 @@ def setup_cl_options(): parser.add_option_group(conn_pool_opt_group) - ## MySQL specifics - mysql_opt_group = OptionGroup(parser, "MySQL-specific options", "These options are specific for MySQL database backend configuration") - mysql_opt_group.add_option("--createdb", dest="createdb", action="store_true", help="Creates the MySQL database schema when installing a VO", default=False) - mysql_opt_group.add_option("--dropdb", dest="dropdb", action="store_true", help="Drops the MySQL database schema when removing a VO", default=False) - - mysql_opt_group.add_option("--dbhost",dest="dbhost", help="Sets the HOST where the MySQL database is running", metavar="HOST", default="localhost") - mysql_opt_group.add_option("--dbport",dest="dbport", type='int', help="Sets the PORT where the MySQL database is listening", metavar="PORT", default="3306") - mysql_opt_group.add_option("--mysql-command", dest="mysql_command", help="Sets the MySQL command to CMD", metavar="CMD", default="mysql") - mysql_opt_group.add_option("--dbauser", dest="dbauser", help="Sets MySQL administrator user to USER", metavar="USER", default="root") - mysql_opt_group.add_option("--dbapwd", dest="dbapwd", help="Sets MySQL administrator password to PWD", metavar="PWD") - mysql_opt_group.add_option("--dbapwdfile", dest="dbapwdfile", help="Reads MySQL administrator password from FILE", metavar="FILE") + # MySQL specifics + mysql_opt_group = OptionGroup(parser, "MySQL-specific options", + "These options are specific for MySQL database backend configuration") + mysql_opt_group.add_option("--createdb", dest="createdb", action="store_true", + help="Creates the MySQL database schema when installing a VO", default=False) + mysql_opt_group.add_option("--dropdb", dest="dropdb", action="store_true", + help="Drops the MySQL database schema when removing a VO", default=False) + + mysql_opt_group.add_option( + "--dbhost", dest="dbhost", help="Sets the HOST where the MySQL database is running", metavar="HOST", default="localhost") + mysql_opt_group.add_option("--dbport", dest="dbport", type='int', + help="Sets the PORT where the MySQL database is listening", metavar="PORT", default="3306") + mysql_opt_group.add_option("--mysql-command", dest="mysql_command", + help="Sets the MySQL command to CMD", metavar="CMD", default="mysql") + mysql_opt_group.add_option("--dburlparams", dest="dburlparams", + help="Sets the DB URL params string", metavar="PARAMS") + mysql_opt_group.add_option("--dbauser", dest="dbauser", + help="Sets MySQL administrator user to USER", metavar="USER", default="root") + mysql_opt_group.add_option( + "--dbapwd", dest="dbapwd", help="Sets MySQL administrator password to PWD", metavar="PWD") + mysql_opt_group.add_option("--dbapwdfile", dest="dbapwdfile", + help="Reads MySQL administrator password from FILE", metavar="FILE") parser.add_option_group(mysql_opt_group) - ## ORACLE specifics - oracle_opt_group = OptionGroup(parser, "Oracle-specific options", "These options are specific for Oracle database backend configuration") - oracle_opt_group.add_option("--use-thin-driver", dest="use_thin_driver", action="store_true", help="Configures the Oracle database using the pure-java native driver", default=False) + # ORACLE specifics + oracle_opt_group = OptionGroup(parser, "Oracle-specific options", + "These options are specific for Oracle database backend configuration") + oracle_opt_group.add_option("--use-thin-driver", dest="use_thin_driver", action="store_true", + help="Configures the Oracle database using the pure-java native driver", default=False) parser.add_option_group(oracle_opt_group) - ## VOMS core specifics - voms_core_opt_group = OptionGroup(parser, "VOMS core options", "These options drive the configuration of the VOMS core service.") - voms_core_opt_group.add_option("--core-port", dest="core_port", type="int", help="the PORT on which the VOMS core service will bind", metavar="PORT") - voms_core_opt_group.add_option("--libdir", dest="libdir", help="the DIR where VOMS core will look for the database plugin modules.", metavar="PORT") - voms_core_opt_group.add_option("--logdir", dest="logdir", help="the VOMS core log directory DIR", metavar="DIR") - voms_core_opt_group.add_option("--sqlloc", dest="sqlloc", help="the PATH to the VOMS core database access library", metavar="PATH") - voms_core_opt_group.add_option("--uri", dest="uri", help="Defines a non-standard the URI of the VOMS server included in the issued attribute certificates", metavar="URI") - voms_core_opt_group.add_option("--timeout", dest="timeout", type="int", help="Defines the validity of the AC issued by the VOMS server in seconds. The default is 24 hours (86400)", metavar="SECS", default=86400) - voms_core_opt_group.add_option("--socktimeout", dest="socktimeout", type="int", help="Sets the amount of time in seconds after which the server will drop an inactive connection. The default is 60 seconds", metavar="SECS", default=60) - voms_core_opt_group.add_option("--shortfqans", dest="shortfqans", action="store_true", help="Configures VOMS to use the short fqans syntax", default=False) - voms_core_opt_group.add_option("--skip-ca-check", dest="skip_ca_check", action="store_true", help="Configures VOMS to only consider a certificate subject when checking VO user membership", default=False) - voms_core_opt_group.add_option("--max-reqs", type="int", dest="max_reqs", help="Sets the maximum number of concurrent request that the VOMS service can handle.", default=50) + # VOMS core specifics + voms_core_opt_group = OptionGroup( + parser, "VOMS core options", "These options drive the configuration of the VOMS core service.") + voms_core_opt_group.add_option("--core-port", dest="core_port", type="int", + help="the PORT on which the VOMS core service will bind", metavar="PORT") + voms_core_opt_group.add_option( + "--libdir", dest="libdir", help="the DIR where VOMS core will look for the database plugin modules.", metavar="PORT") + voms_core_opt_group.add_option( + "--logdir", dest="logdir", help="the VOMS core log directory DIR", metavar="DIR") + voms_core_opt_group.add_option( + "--sqlloc", dest="sqlloc", help="the PATH to the VOMS core database access library", metavar="PATH") + voms_core_opt_group.add_option( + "--uri", dest="uri", help="Defines a non-standard the URI of the VOMS server included in the issued attribute certificates", metavar="URI") + voms_core_opt_group.add_option("--timeout", dest="timeout", type="int", + help="Defines the validity of the AC issued by the VOMS server in seconds. The default is 24 hours (86400)", metavar="SECS", default=86400) + voms_core_opt_group.add_option("--socktimeout", dest="socktimeout", type="int", + help="Sets the amount of time in seconds after which the server will drop an inactive connection. The default is 60 seconds", metavar="SECS", default=60) + voms_core_opt_group.add_option("--shortfqans", dest="shortfqans", action="store_true", + help="Configures VOMS to use the short fqans syntax", default=False) + voms_core_opt_group.add_option("--skip-ca-check", dest="skip_ca_check", action="store_true", + help="Configures VOMS to only consider a certificate subject when checking VO user membership", default=False) + voms_core_opt_group.add_option("--max-reqs", type="int", dest="max_reqs", + help="Sets the maximum number of concurrent request that the VOMS service can handle.", default=50) parser.add_option_group(voms_core_opt_group) - ## Registration service specifics - registration_opt_group = OptionGroup(parser, "Registration service options", "These options configure the VOMS Admin registration service") - registration_opt_group.add_option("--disable-registration", dest="enable_registration", action="store_false", help="Disables registration service for the VO", default=True) - registration_opt_group.add_option("--aup-url", dest="aup_url", help="Sets a custom URL for the VO AUP.", metavar="URL") + # Registration service specifics + registration_opt_group = OptionGroup( + parser, "Registration service options", "These options configure the VOMS Admin registration service") + registration_opt_group.add_option("--disable-registration", dest="enable_registration", + action="store_false", help="Disables registration service for the VO", default=True) + registration_opt_group.add_option( + "--aup-url", dest="aup_url", help="Sets a custom URL for the VO AUP.", metavar="URL") registration_opt_group.add_option("--aup-signature-grace-period", type="int", dest="aup_signature_grace_period", help="The time (in days) given to users to sign the AUP, after being notified, before being suspended.", metavar="DAYS", default="15") - + registration_opt_group.add_option("--aup-reminders", dest="aup_reminders", help="Comma-separated list of instants (in days) before the end of AUP grace period when reminders must be sent to users that need to sign the AUP.", @@ -247,17 +301,17 @@ def setup_cl_options(): registration_opt_group.add_option("--enable-attribute-requests", dest="enable_attribute_requests", action="store_true", help="Enable attribute request at registration time.", default=False) - - registration_opt_group.add_option("--disable-mandatory-group-manager-selection", - dest="require_group_manager_selection", + + registration_opt_group.add_option("--disable-mandatory-group-manager-selection", + dest="require_group_manager_selection", action="store_false", - help="Disable manadatory group manager selection.", + help="Disable manadatory group manager selection.", default=True) registration_opt_group.add_option("--group-manager-role", type="string", dest="group_manager_role", help="Group manager role name. (default value: Group-Manager)", default="Group-Manager") - + registration_opt_group.add_option("--membership-request-lifetime", type="int", dest="membership_request_lifetime", help="Time (in seconds) that unconfirmed membership request are maintained in the VOMS database.", metavar="SECS", default=604800) @@ -270,19 +324,25 @@ def setup_cl_options(): parser.add_option_group(registration_opt_group) + # Membership checks configuration + membership_opt_group = OptionGroup( + parser, "Membership checks options", "These options configure the VOMS Admin membership checks") - ## Membership checks configuration - membership_opt_group = OptionGroup(parser, "Membership checks options", "These options configure the VOMS Admin membership checks") + membership_opt_group.add_option("--preserve-expired-members", action="store_true", dest="preserve_expired_members", + help="Do not suspend users whose membership has expired.", default=False) + membership_opt_group.add_option("--preserve-aup-failing-members", action="store_true", dest="preserve_aup_failing_members", + help="Do not suspend users that fail to sign the AUP in time.", default=False) + membership_opt_group.add_option("--disable-membership-end-time", action="store_true", + dest="disable_membership_end_time", help="Disable membership end time checks completely.", default=False) - membership_opt_group.add_option("--preserve-expired-members", action="store_true", dest="preserve_expired_members", help="Do not suspend users whose membership has expired.", default=False) - membership_opt_group.add_option("--preserve-aup-failing-members", action="store_true", dest="preserve_aup_failing_members", help="Do not suspend users that fail to sign the AUP in time.", default=False) - membership_opt_group.add_option("--disable-membership-end-time", action="store_true", dest="disable_membership_end_time", help="Disable membership end time checks completely.", default=False) - - membership_opt_group.add_option("--disable-membership-expiration-warnings", action="store_true", dest="disable_membership_expiration_warning", help="Disable membership expiration warnings.", default=False) + membership_opt_group.add_option("--disable-membership-expiration-warnings", action="store_true", + dest="disable_membership_expiration_warning", help="Disable membership expiration warnings.", default=False) - membership_opt_group.add_option("--membership-default-lifetime", type="int", dest="membership_default_lifetime", help="Default VO membership lifetime duration (in months).", metavar="MONTHS", default=12) + membership_opt_group.add_option("--membership-default-lifetime", type="int", dest="membership_default_lifetime", + help="Default VO membership lifetime duration (in months).", metavar="MONTHS", default=12) - membership_opt_group.add_option("--membership-check-period", type="int", dest="membership_check_period", help="The membership check background thread period (in seconds)", metavar="SECS", default=600) + membership_opt_group.add_option("--membership-check-period", type="int", dest="membership_check_period", + help="The membership check background thread period (in seconds)", metavar="SECS", default=600) membership_opt_group.add_option("--membership-expiration-warning-period", type="int", dest="membership_expiration_warning_period", help="Warning period duration (in days). VOMS Admin will notify of users about to expire in the next number of days expressed by this configuration option.", @@ -296,12 +356,14 @@ def setup_cl_options(): help="Time (in days) that should pass between consecutive warning expiration messages sent to VO administrators to inform about expired and expiring VO members.", metavar="DAYS", default=1) - parser.add_option_group(membership_opt_group) - saml_opt_group = OptionGroup(parser, "SAML Attribute Authority options", "These options configure the VOMS SAML attribute authority service") - saml_opt_group.add_option("--enable-saml", dest="enable_saml", action="store_true", help="Turns on the VOMS SAML service.", default=False) - saml_opt_group.add_option("--saml-lifetime", dest="saml_lifetime", type="int", help="Defines the maximum validity of the SAML assertions issued by the VOMS SAML server in seconds. The default is 24 hours (86400)", metavar="SECS", default=86400) + saml_opt_group = OptionGroup(parser, "SAML Attribute Authority options", + "These options configure the VOMS SAML attribute authority service") + saml_opt_group.add_option("--enable-saml", dest="enable_saml", action="store_true", + help="Turns on the VOMS SAML service.", default=False) + saml_opt_group.add_option("--saml-lifetime", dest="saml_lifetime", type="int", + help="Defines the maximum validity of the SAML assertions issued by the VOMS SAML server in seconds. The default is 24 hours (86400)", metavar="SECS", default=86400) saml_opt_group.add_option("--disable-compulsory-group-membership", action="store_false", dest="compulsory_group_membership", @@ -309,9 +371,10 @@ def setup_cl_options(): parser.add_option_group(saml_opt_group) - - x509aa_opt_group = OptionGroup(parser, "X.509 AC Attribute Authority options", "These options configure the VOMS X.509 attribute authority service") - x509aa_opt_group.add_option("--enable-x509-aa", dest="enable_x509_aa", action="store_true", help="Turns on the X.509 Attribute authority", default=False) + x509aa_opt_group = OptionGroup(parser, "X.509 AC Attribute Authority options", + "These options configure the VOMS X.509 attribute authority service") + x509aa_opt_group.add_option("--enable-x509-aa", dest="enable_x509_aa", action="store_true", + help="Turns on the X.509 Attribute authority", default=False) x509aa_opt_group.add_option("--x509-aa-port", dest="x509_aa_port", type="int", help="An additional port used to serve VOMS legacy request.", @@ -329,17 +392,25 @@ def setup_cl_options(): parser.add_option_group(x509aa_opt_group) - notification_opt_group = OptionGroup(parser, "Notification service options", "These options configure the VOMS Admin notification service") - notification_opt_group.add_option("--mail-from", dest="mail_from",help="The EMAIL address used for VOMS Admin notification messages.", metavar="EMAIL") - notification_opt_group.add_option("--smtp-host", dest="smtp_host",help="The HOST where VOMS Admin will deliver notification messages.", metavar="HOST") - notification_opt_group.add_option("--disable-notification", dest="disable_notification", action="store_true", help=" Turns off the VOMS admin notification service.", default=False) - notification_opt_group.add_option("--notification-username", dest="notification_username",help="SMTP authentication USERNAME", metavar="USERNAME", default="") - notification_opt_group.add_option("--notification-password", dest="notification_password",help="SMTP authentication PASSWORD", metavar="PASSWORD", default="") - notification_opt_group.add_option("--notification-use-tls", action="store_true", dest="notification_use_tls",help="Use TLS to connect to SMTP server", default=False) + notification_opt_group = OptionGroup( + parser, "Notification service options", "These options configure the VOMS Admin notification service") + notification_opt_group.add_option( + "--mail-from", dest="mail_from", help="The EMAIL address used for VOMS Admin notification messages.", metavar="EMAIL") + notification_opt_group.add_option( + "--smtp-host", dest="smtp_host", help="The HOST where VOMS Admin will deliver notification messages.", metavar="HOST") + notification_opt_group.add_option("--disable-notification", dest="disable_notification", + action="store_true", help=" Turns off the VOMS admin notification service.", default=False) + notification_opt_group.add_option("--notification-username", dest="notification_username", + help="SMTP authentication USERNAME", metavar="USERNAME", default="") + notification_opt_group.add_option("--notification-password", dest="notification_password", + help="SMTP authentication PASSWORD", metavar="PASSWORD", default="") + notification_opt_group.add_option("--notification-use-tls", action="store_true", + dest="notification_use_tls", help="Use TLS to connect to SMTP server", default=False) parser.add_option_group(notification_opt_group) - other_opt_group = OptionGroup(parser, "Other fancy options", "Configuration options that do not fall in the other categories") + other_opt_group = OptionGroup(parser, "Other fancy options", + "Configuration options that do not fall in the other categories") other_opt_group.add_option("--disable-conf-backup", dest="enable_conf_backup", action="store_false", @@ -361,14 +432,13 @@ def setup_cl_options(): parser.add_option_group(other_opt_group) - def configure_logging(options): """ Configures logging so that debug and info messages are routed to stdout and higher level messages are to stderr. Debug messages are shown only if verbose option is set """ class InfoAndBelowLoggingFilter(logging.Filter): - def filter(self,record): + def filter(self, record): if record.levelno <= logging.INFO: return 1 return 0 @@ -390,9 +460,10 @@ def filter(self,record): logger = logging.getLogger("voms-admin") logger.addHandler(out) logger.addHandler(err) - logger.propagate=False + logger.propagate = False logger.debug("Logging configured") + def check_required_options(options, required_opts): def option_name_from_var(var_name): return "--"+re.sub(r'_', '-', var_name) @@ -403,7 +474,8 @@ def option_name_from_var(var_name): missing_opts.append(option_name_from_var(o)) if len(missing_opts) > 0: - error_and_exit("Please set the following required options:\n\t%s" % '\n\t'.join(missing_opts)) + error_and_exit( + "Please set the following required options:\n\t%s" % '\n\t'.join(missing_opts)) def check_install_options(options): @@ -412,7 +484,8 @@ def check_install_options(options): error_and_exit("Please set the VO option") if options.skip_voms_core and options.skip_voms_admin: - error_and_exit("There's not much to do if --skip-voms-core and --skip-voms-admin are both set!") + error_and_exit( + "There's not much to do if --skip-voms-core and --skip-voms-admin are both set!") required_opts = ["vo", "dbusername", "dbpassword"] @@ -433,10 +506,12 @@ def check_remove_options(options): if not options.vo: error_and_exit("Please set the VO option") + def check_upgrade_options(options): if not options.vo: error_and_exit("Please set the VO option") + def service_cert_sanity_checks(options): if not os.path.exists(options.cert): error_and_exit("Service certificate %s not found." % options.cert) @@ -445,55 +520,66 @@ def service_cert_sanity_checks(options): error_and_exit("Service private key %s not found." % options.key) if not os.path.exists(options.trust_dir): - error_and_exit("Service trust anchor directory %s not found." % options.trust_dir) + error_and_exit( + "Service trust anchor directory %s not found." % options.trust_dir) + def config_owner_ids(options): try: pwd_info = pwd.getpwnam(options.config_owner) return (pwd_info[2], pwd_info[3]) except KeyError: - logger.warn("User %s is not configured on this system." % options.config_owner) + logger.warn("User %s is not configured on this system." % + options.config_owner) if os.geteuid() == 0: - error_and_exit("User %s is not configured on this system." % options.config_owner) + error_and_exit( + "User %s is not configured on this system." % options.config_owner) + def create_voms_service_certificate(options): if os.geteuid() == 0 and not options.dry_run: - logger.info("Creating VOMS services certificate in %s, %s" % (VOMS_CERT, VOMS_KEY)) + logger.info("Creating VOMS services certificate in %s, %s" % + (VOMS_CERT, VOMS_KEY)) shutil.copy(HOST_CERT, VOMS_CERT) shutil.copy(HOST_KEY, VOMS_KEY) (owner_id, owner_group_id) = config_owner_ids(options) - os.chown(VOMS_CERT,owner_id, owner_group_id) - os.chown(VOMS_KEY,owner_id, owner_group_id) + os.chown(VOMS_CERT, owner_id, owner_group_id) + os.chown(VOMS_KEY, owner_id, owner_group_id) - os.chmod(VOMS_CERT,0644) - os.chmod(VOMS_KEY,0400) + os.chmod(VOMS_CERT, 0644) + os.chmod(VOMS_KEY, 0400) options.cert = VOMS_CERT options.key = VOMS_KEY + def setup_service_certificate(options): service_cert_sanity_checks(options) if options.cert == HOST_CERT and options.key == HOST_KEY and os.geteuid() == 0: create_voms_service_certificate(options) + def driver_class(options): if options.dbtype == MYSQL: return VOMSDefaults.mysql_driver_class if options.dbtype == ORACLE: return VOMSDefaults.oracle_driver_class + def driver_dialect(options): if options.dbtype == MYSQL: return VOMSDefaults.mysql_dialect else: return VOMSDefaults.oracle_dialect + def change_owner_and_set_perms(path, owner_id, group_id, perms): if os.geteuid() == 0: os.chown(path, owner_id, group_id) os.chmod(path, perms) + def write_and_set_permissions(options, path, contents, perms): f = open(path, "w") f.write(contents) @@ -501,7 +587,8 @@ def write_and_set_permissions(options, path, contents, perms): os.chmod(path, perms) if os.getuid() == 0: (owner_id, group_id) = config_owner_ids(options) - os.chown(path,owner_id,group_id) + os.chown(path, owner_id, group_id) + def append_and_set_permissions(path, contents, owner_id, group_id, perms): f = open(path, "a") @@ -509,10 +596,18 @@ def append_and_set_permissions(path, contents, owner_id, group_id, perms): f.close() change_owner_and_set_perms(path, owner_id, group_id, perms) + def dburl_mysql(options): - return "jdbc:mysql://%s:%d/%s" % (options.dbhost, - options.dbport, - options.dbname) + if options.dburlparams: + return "jdbc:mysql://%s:%d/%s?%s" % (options.dbhost, + options.dbport, + options.dbname, + options.dburlparams) + else: + return "jdbc:mysql://%s:%d/%s" % (options.dbhost, + options.dbport, + options.dbname) + def dburl_oracle(options): if options.use_thin_driver: @@ -522,20 +617,24 @@ def dburl_oracle(options): else: return "jdbc:oracle:oci:@%s" % (options.dbname) + def dburl(options): if options.dbtype == MYSQL: return dburl_mysql(options) else: return dburl_oracle(options) + def create_admin_db_properties(options): db_options = dict(dbdriver=driver_class(options), dbdialect=driver_dialect(options), dburl=dburl(options)) - template = string.Template(open(VOMSDefaults.db_props_template,"r").read()) - db_properties = template.substitute(**dict(db_options.items()+options.__dict__.items())) + template = string.Template( + open(VOMSDefaults.db_props_template, "r").read()) + db_properties = template.substitute( + **dict(db_options.items()+options.__dict__.items())) logger.debug("Admin service database properties:\n%s" % db_properties) @@ -545,8 +644,10 @@ def create_admin_db_properties(options): db_properties, 0640) + def create_admin_service_properties(options): - template = string.Template(open(VOMSDefaults.service_props_template,"r").read()) + template = string.Template( + open(VOMSDefaults.service_props_template, "r").read()) service_props = template.substitute(**options.__dict__) logger.debug("Admin service properties:\n%s" % service_props) @@ -556,6 +657,7 @@ def create_admin_service_properties(options): service_props, 0640) + def create_endpoint_info(options): endpoint_path = admin_service_endpoint_path(options.vo) @@ -566,6 +668,8 @@ def create_endpoint_info(options): endpoint_path, url, 0644) + + def create_vomses(options): cert = X509Helper(options.cert, openssl_cmd=options.openssl) @@ -585,6 +689,8 @@ def create_vomses(options): vomses_path(options.vo), vomses, 0644) + + def create_lsc(options): cert = X509Helper(options.cert, openssl_cmd=options.openssl) lsc = "%s\n%s" % (cert.subject, cert.issuer) @@ -594,9 +700,11 @@ def create_lsc(options): lsc_path(options.vo), lsc, 0644) + + def create_aup(options): if not options.dry_run: - shutil.copyfile(VOMSDefaults.vo_aup_template,aup_path(options.vo)) + shutil.copyfile(VOMSDefaults.vo_aup_template, aup_path(options.vo)) if os.geteuid() == 0: (owner_id, group_id) = config_owner_ids(options) change_owner_and_set_perms(aup_path(options.vo), @@ -604,9 +712,11 @@ def create_aup(options): group_id, 0644) + def create_logging_configuration(options): if not options.dry_run: - shutil.copyfile(VOMSDefaults.logging_conf_template,admin_logging_conf_path(options.vo)) + shutil.copyfile(VOMSDefaults.logging_conf_template, + admin_logging_conf_path(options.vo)) if os.geteuid() == 0: (owner_id, group_id) = config_owner_ids(options) change_owner_and_set_perms(admin_logging_conf_path(options.vo), @@ -614,20 +724,22 @@ def create_logging_configuration(options): group_id, 0644) + def create_admin_configuration(options): if os.path.exists(admin_conf_dir(options.vo)): - logger.info("VOMS Admin service configuration for VO %s exists.", options.vo) + logger.info( + "VOMS Admin service configuration for VO %s exists.", options.vo) if not options.dry_run and options.enable_conf_backup: backup_dir_contents(admin_conf_dir(options.vo)) else: - ## Set the deploy database option if the VO is - ## installed for the first time on this host and this - ## is not meant as a replica + # Set the deploy database option if the VO is + # installed for the first time on this host and this + # is not meant as a replica if not options.skip_database: options.deploy_database = True # options.createdb = True - ## FIXME: set permissions + # FIXME: set permissions if not options.dry_run: os.makedirs(admin_conf_dir(options.vo)) @@ -643,28 +755,27 @@ def create_admin_configuration(options): def create_voms_conf(options): core_opts = dict(core_logfile=os.path.join(options.logdir, "voms.%s" % options.vo), - core_passfile=voms_pass_path(options.vo), - core_sqlloc=os.path.join(options.libdir, options.sqlloc)) - + core_passfile=voms_pass_path(options.vo), + core_sqlloc=os.path.join(options.libdir, options.sqlloc)) - template = string.Template(open(VOMSDefaults.voms_template,"r").read()) + template = string.Template(open(VOMSDefaults.voms_template, "r").read()) all_core_opts = dict(core_opts.items() + options.__dict__.items()) voms_props = template.substitute(**all_core_opts) if options.skip_ca_check: - voms_props+="\n--skipcacheck" + voms_props += "\n--skipcacheck" if options.shortfqans: - voms_props+="\n--shortfqans" + voms_props += "\n--shortfqans" logger.debug("VOMS Core configuration:\n%s" % voms_props) if not options.dry_run: - ## Core configuration + # Core configuration write_and_set_permissions(options, voms_conf_path(options.vo), voms_props, 0644) - ## Core password file + # Core password file write_and_set_permissions(options, voms_pass_path(options.vo), options.dbpassword+"\n", @@ -672,13 +783,15 @@ def create_voms_conf(options): logger.info("VOMS core service configured succesfully.") + def create_core_configuration(options): if os.path.exists(core_conf_dir(options.vo)): - logger.info("VOMS core service configuration for VO %s already exists.", options.vo) + logger.info( + "VOMS core service configuration for VO %s already exists.", options.vo) if not options.dry_run and options.enable_conf_backup: backup_dir_contents(core_conf_dir(options.vo)) else: - ## FIXME: set permissions + # FIXME: set permissions os.makedirs(core_conf_dir(options.vo)) create_voms_conf(options) @@ -687,6 +800,7 @@ def create_core_configuration(options): def generate_password(length=8, chars=string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for x in range(length)) + def setup_core_defaults(options): if not options.uri: options.uri = "%s:%d" % (options.hostname, options.core_port) @@ -706,7 +820,7 @@ def setup_core_defaults(options): def setup_defaults(options): if not options.dbname and options.dbtype == MYSQL: - options.dbname = "voms_%s" % (re.sub(r"[-.]","_",options.vo)) + options.dbname = "voms_%s" % (re.sub(r"[-.]", "_", options.vo)) if not options.dbhost: options.dbhost = "localhost" @@ -721,39 +835,52 @@ def setup_defaults(options): if options.createdb or options.dropdb: if not options.dbapwd: - error_and_exit("Please set at least the --dbapwd option when attempting MySQL schema creation/removal.") + error_and_exit( + "Please set at least the --dbapwd option when attempting MySQL schema creation/removal.") + def setup_admin_defaults(options): if not options.aup_url: options.aup_url = "file:%s" % aup_path(options.vo) + def create_mysql_db(options): createdb_cmd = mysql_util_cmd("create_db", options) if not options.dbapwd or len(options.dbapwd) == 0: - logger.warn("WARNING: No password has been specified for the mysql root account.") + logger.warn( + "WARNING: No password has been specified for the mysql root account.") execute_cmd(createdb_cmd, "Error creating MySQL database schema.") + def deploy_database(options): logger.info("Deploying database for VO %s", options.vo) if options.dbtype == MYSQL and options.createdb: create_mysql_db(options) - execute_cmd(voms_deploy_database_cmd(options.vo), "Error deploying VOMS database!") - logger.info("Adding VO administrator reading information from %s", options.cert) - execute_cmd(voms_add_admin_cmd(options.vo, options.cert, ignore_email=True), "Error adding VO administrator!") + execute_cmd(voms_deploy_database_cmd(options.vo), + "Error deploying VOMS database!") + logger.info( + "Adding VO administrator reading information from %s", options.cert) + execute_cmd(voms_add_admin_cmd(options.vo, options.cert, + ignore_email=True), "Error adding VO administrator!") if options.read_only_auth_clients: - logger.info("Adding read-only access to authenticated clients on the VO.") - execute_cmd(voms_ro_auth_clients_cmd(options.vo), "Error setting read-only access on the VO!") + logger.info( + "Adding read-only access to authenticated clients on the VO.") + execute_cmd(voms_ro_auth_clients_cmd(options.vo), + "Error setting read-only access on the VO!") if options.admin_cert: - logger.info("Adding VO administrator reading information from %s", options.admin_cert) - execute_cmd(voms_add_admin_cmd(options.vo, options.admin_cert), "Error adding VO administrator!") + logger.info( + "Adding VO administrator reading information from %s", options.admin_cert) + execute_cmd(voms_add_admin_cmd(options.vo, options.admin_cert), + "Error adding VO administrator!") + def do_admin_install(options): - logger.info("Configuring VOMS admin service for vo %s" , options.vo) + logger.info("Configuring VOMS admin service for vo %s", options.vo) setup_service_certificate(options) setup_admin_defaults(options) create_admin_configuration(options) @@ -763,7 +890,7 @@ def do_admin_install(options): def do_core_install(options): - logger.info("Configuring VOMS core service for vo %s" , options.vo) + logger.info("Configuring VOMS core service for vo %s", options.vo) if options.skip_voms_admin: setup_service_certificate(options) @@ -771,6 +898,7 @@ def do_core_install(options): create_core_configuration(options) pass + def do_install(options): check_install_options(options) setup_defaults(options) @@ -789,41 +917,49 @@ def upgrade_database(options): def undeploy_database(options): - logger.warning("Undeploying database for VO %s. The database contents will be lost.", options.vo) + logger.warning( + "Undeploying database for VO %s. The database contents will be lost.", options.vo) if options.dbtype == MYSQL and options.dropdb: - execute_cmd(mysql_util_cmd("drop_db", options), "Error dropping MySQL database for VO %s!" % options.vo) + execute_cmd(mysql_util_cmd("drop_db", options), + "Error dropping MySQL database for VO %s!" % options.vo) else: - execute_cmd(voms_undeploy_database_cmd(options.vo), "Error undeploying VOMS database for VO %s!" % (options.vo)) + execute_cmd(voms_undeploy_database_cmd(options.vo), + "Error undeploying VOMS database for VO %s!" % (options.vo)) + def remove_dir_and_contents(directory): logger.info("Removing directory %s and its contents", directory) if os.path.exists(directory): for i in glob.glob(directory+"/*"): - logger.debug("Removing %s",i) + logger.debug("Removing %s", i) os.remove(i) os.rmdir(directory) + def do_remove(options): check_remove_options(options) setup_defaults(options) if not options.skip_voms_admin: if not os.path.exists(admin_conf_dir(options.vo)): - logger.error("The VOMS Admin service for VO %s is not configured on this host.", options.vo) + logger.error( + "The VOMS Admin service for VO %s is not configured on this host.", options.vo) else: if options.undeploy_database: if not options.skip_database: undeploy_database(options) else: - logger.warning("Database will not be dropped since --skip-database option is set.") + logger.warning( + "Database will not be dropped since --skip-database option is set.") logger.info("Removing VOMS Admin service configuration") remove_dir_and_contents(admin_conf_dir(options.vo)) if not options.skip_voms_core: if not os.path.exists(core_conf_dir(options.vo)): - logger.error("The VOMS core service for VO %s is not configured on this host.", options.vo) + logger.error( + "The VOMS core service for VO %s is not configured on this host.", options.vo) else: logger.info("Removing VOMS core service configuration") remove_dir_and_contents(core_conf_dir(options.vo)) @@ -834,17 +970,20 @@ def do_upgrade(options): setup_defaults(options) if not os.path.exists(admin_conf_dir(options.vo)): - logger.error("The VOMS Admin service for VO %s is not configured on this host.", options.vo) + logger.error( + "The VOMS Admin service for VO %s is not configured on this host.", options.vo) else: logger.info("Upgrading database for VO %s to the latest version.", options.vo) upgrade_database(options) logger.info("Upgrade completed successfully.") + def error_and_exit(msg): logger.critical(msg) exit(1) + def main(): setup_cl_options() (options, args) = parser.parse_args() @@ -864,5 +1003,6 @@ def main(): except: logger.exception("Unexpected error caught!") + if __name__ == '__main__': main() From 2b08819399861cf634e0e910a3d988e7721f1c66 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 24 Sep 2020 17:14:26 +0200 Subject: [PATCH 53/63] Bumped version to 3.8.0.rc0 --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 1191 ++++++++++++++++++------------------- voms-container/pom.xml | 2 +- 4 files changed, 598 insertions(+), 599 deletions(-) diff --git a/pom.xml b/pom.xml index 2b1f065b..71342bea 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.8.0-SNAPSHOT + 3.8.0.rc0 pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index dc7183bf..1d538a81 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.8.0-SNAPSHOT + 3.8.0.rc0 voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index f722e951..96959ad3 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -1,601 +1,600 @@ - - + - 4.0.0 - - - org.italiangrid - voms-admin-parent - 3.8.0-SNAPSHOT - - - voms-admin-server - war - VOMS Admin Server - - - ${project.version} - ${project.version} - 2.0.2 - - 2.5.22 - 2.5.2 - 4.0.3 - 5.2.17.Final - 0.9.5.4 - 2.5.3 - 3.0.8 - 3.2 - 5.5.1 - 2.2 - - - - - - ${basedir}/src/main/resources - - voms-admin.tld - version.properties - packaging.properties - - - - ${basedir}/src/main/resources - - version.properties - packaging.properties - logback.vomses.xml - rebel.xml - - true - - - - - org.apache.maven.plugins - maven-jar-plugin - - - package - - jar - - - - - - - - org.apache.maven.plugins - maven-war-plugin - - - - WEB-INF/classes/logback*.xml, - WEB-INF/lib/javax*.jar, - WEB-INF/lib/jetty-all-server*.jar, - WEB-INF/lib/jetty-jsp-*.jar, - WEB-INF/lib/bcmail-*.jar, - WEB-INF/lib/bcprov-*.jar, - WEB-INF/lib/canl-*.jar, - WEB-INF/lib/voms-api-java-*.jar, - WEB-INF/lib/https-utils-*.jar, - WEB-INF/lib/org.apache.jasper.*.jar, - WEB-INF/lib/org.eclipse.jdt.core*.jar, - WEB-INF/lib/voms-container*.jar - - - - ${basedir}/src/main/resources - - voms-admin.tld - - - WEB-INF/classes/org/glite/security/voms/admin/jsp - - - - - - - - com.mycila - license-maven-plugin - -
    ${project.parent.basedir}/license/license.txt
    - - src/test/resources/** - **/*.sql - **/*.jpage - **/*.template - **/*.wsdl - **/*.tld - **/*.wsdd - **/*.spec - **/*.pydevproject - **/*.js - **/rebel.xml - bin/** - src/config/sysconfig - src/main/webapp/common/struts/** - src/main/webapp/struts/** - src/main/webapp/style/** - src/main/webapp/assets/** - src/main/webapp/css/** - src/main/webapp/fonts/** - src/main/webapp/jquery-ui/** - src/main/webapp/jsps/** - src/main/resources/vomses-webapp/** - **/*.gitignore - resources/doc/** - resources/scripts/** - resources/templates/aup/** - resources/templates/** - - true -
    - - - check-headers - verify - - check - - - -
    -
    - - voms-admin -
    - - - - - commons-io - commons-io - ${commons-io.version} - - - - org.italiangrid - voms-admin-api - ${project.version} - - - - org.italiangrid - voms-container - ${project.version} - - - - junit - junit - - - - org.hamcrest - hamcrest-core - test - - - - org.hamcrest - hamcrest-library - test - - - - org.mockito - mockito-core - test - - - - org.mock-server - mockserver-netty - ${mock-server.version} - test - - - - org.mock-server - mockserver-client-java - ${mock-server.version} - test - - - - org.hibernate - hibernate-core - ${hibernate.version} - - - commons-logging - commons-logging - - - asm - asm-attrs - - - asm - asm - - - - - - org.hibernate - hibernate-c3p0 - ${hibernate.version} - - - - com.google.guava - guava - provided - - - - com.mchange - c3p0 - ${c3p0.version} - runtime - - - - org.eclipse.jetty - jetty-jsp - - - - org.eclipse.jetty - jetty-client - - - - javax.mail - mail - - - javax.activation - activation - - - - - - commons-collections - commons-collections - 3.2.2 - - - - commons-configuration - commons-configuration - 1.5 - - - commons-logging - commons-logging - - - - - - commons-cli - commons-cli - - - - org.apache.commons - commons-email - 1.1 - - - - org.apache.velocity - velocity - 1.5 - - - - org.apache.commons - commons-math3 - ${commons-math.version} - - - - - mysql - mysql-connector-java - 8.0.16 - - - - - org.apache.struts - struts2-core - ${struts.version} - - - javassist - javassist - - - - - - org.apache.struts - struts2-convention-plugin + 4.0.0 + + + org.italiangrid + voms-admin-parent + 3.8.0.rc0 + + + voms-admin-server + war + VOMS Admin Server + + + ${project.version} + ${project.version} + 2.0.2 + + 2.5.22 + 2.5.2 + 4.0.3 + 5.2.17.Final + 0.9.5.4 + 2.5.3 + 3.0.8 + 3.2 + 5.5.1 + 2.2 + 2.13.3 + + + + + + ${basedir}/src/main/resources + + voms-admin.tld + version.properties + packaging.properties + + + + ${basedir}/src/main/resources + + version.properties + packaging.properties + logback.vomses.xml + rebel.xml + + true + + + + + org.apache.maven.plugins + maven-jar-plugin + + + package + + jar + + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + WEB-INF/classes/logback*.xml, + WEB-INF/lib/javax*.jar, + WEB-INF/lib/jetty-all-server*.jar, + WEB-INF/lib/jetty-jsp-*.jar, + WEB-INF/lib/bcmail-*.jar, + WEB-INF/lib/bcprov-*.jar, + WEB-INF/lib/canl-*.jar, + WEB-INF/lib/voms-api-java-*.jar, + WEB-INF/lib/https-utils-*.jar, + WEB-INF/lib/org.apache.jasper.*.jar, + WEB-INF/lib/org.eclipse.jdt.core*.jar, + WEB-INF/lib/voms-container*.jar + + + + ${basedir}/src/main/resources + + voms-admin.tld + + + WEB-INF/classes/org/glite/security/voms/admin/jsp + + + + + + + + com.mycila + license-maven-plugin + +
    ${project.parent.basedir}/license/license.txt
    + + src/test/resources/** + **/*.sql + **/*.jpage + **/*.template + **/*.wsdl + **/*.tld + **/*.wsdd + **/*.spec + **/*.pydevproject + **/*.js + **/rebel.xml + bin/** + src/config/sysconfig + src/main/webapp/common/struts/** + src/main/webapp/struts/** + src/main/webapp/style/** + src/main/webapp/assets/** + src/main/webapp/css/** + src/main/webapp/fonts/** + src/main/webapp/jquery-ui/** + src/main/webapp/jsps/** + src/main/resources/vomses-webapp/** + **/*.gitignore + resources/doc/** + resources/scripts/** + resources/templates/aup/** + resources/templates/** + + true +
    + + + check-headers + verify + + check + + + +
    +
    + + voms-admin +
    + + + + + commons-io + commons-io + ${commons-io.version} + + + + org.italiangrid + voms-admin-api + ${project.version} + + + + org.italiangrid + voms-container + ${project.version} + + + + junit + junit + + + + org.hamcrest + hamcrest-core + test + + + + org.hamcrest + hamcrest-library + test + + + + org.mockito + mockito-core + test + + + + org.mock-server + mockserver-netty + ${mock-server.version} + test + + + + org.mock-server + mockserver-client-java + ${mock-server.version} + test + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + commons-logging + commons-logging + + + asm + asm-attrs + + + asm + asm + + + + + + org.hibernate + hibernate-c3p0 + ${hibernate.version} + + + + com.google.guava + guava + provided + + + + com.mchange + c3p0 + ${c3p0.version} + runtime + + + + org.eclipse.jetty + jetty-jsp + + + + org.eclipse.jetty + jetty-client + + + + javax.mail + mail + + + javax.activation + activation + + + + + + commons-collections + commons-collections + 3.2.2 + + + + commons-configuration + commons-configuration + 1.5 + + + commons-logging + commons-logging + + + + + + commons-cli + commons-cli + + + + org.apache.commons + commons-email + 1.1 + + + + org.apache.velocity + velocity + 1.5 + + + + org.apache.commons + commons-math3 + ${commons-math.version} + + + + + mysql + mysql-connector-java + 8.0.16 + + + + + org.apache.struts + struts2-core + ${struts.version} + + + javassist + javassist + + + + + + org.apache.struts + struts2-convention-plugin - ${struts.version} - - - - com.jgeppert.struts2.bootstrap - struts2-bootstrap-plugin - ${struts.bootstrap.plugin.version} - - - - com.jgeppert.struts2.jquery - struts2-jquery-plugin - ${struts.jquery.plugin.version} - - - - org.apache.struts - struts2-tiles-plugin - ${struts.version} - - - commons-logging - commons-logging-api - - - - - - - org.apache.tiles - tiles-jsp - ${tiles.version} - - - - org.apache.struts - struts2-json-plugin + ${struts.version} + + + + com.jgeppert.struts2.bootstrap + struts2-bootstrap-plugin + ${struts.bootstrap.plugin.version} + + + + com.jgeppert.struts2.jquery + struts2-jquery-plugin + ${struts.jquery.plugin.version} + + + + org.apache.struts + struts2-tiles-plugin + ${struts.version} + + + commons-logging + commons-logging-api + + + + + + + org.apache.tiles + tiles-jsp + ${tiles.version} + + + + org.apache.struts + struts2-json-plugin - ${struts.version} - - - - - org.opensaml - opensaml - ${opensaml.version} - - - org.slf4j - slf4j-api - - - org.slf4j - slf4j-log4j12 - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - log4j-over-slf4j - - - org.slf4j - jul-to-slf4j - - - org.slf4j - jcl104-over-slf4j - - - org.bouncycastle - bcprov-ext-jdk15 - - - org.bouncycastle - bcprov-jdk15 - - - velocity - velocity - - - - - - - - org.slf4j - slf4j-api - - - - org.slf4j - log4j-over-slf4j - - - - org.slf4j - jcl-over-slf4j - - - - ch.qos.logback - logback-core - - - - ch.qos.logback - logback-classic - - - - org.italiangrid - https-utils - - - - - - EMI - - true - - - - / - /etc/voms-admin - voms - /usr/lib64/oracle/11.2.0.3.0/client/lib64 - /etc/voms - - - - - - maven-assembly-plugin - - - ${basedir}/src/assemble/tarball.xml - - voms-admin - - - - package - - single - - - - - - - - - - dev - - - /opt/voms/ - /opt/voms/etc/voms-admin - - /usr/lib64/oracle/11.2.0.3.0/client/lib64 - /opt/voms/etc/voms - - - - - prod - - - - - - - org.apache.maven.plugins - maven-war-plugin - - - ${basedir}/target/web.xml - - - WEB-INF/classes/logback*.xml, - WEB-INF/lib/javax*.jar, - WEB-INF/lib/jetty-all-server*.jar, - WEB-INF/lib/jetty-jsp-*.jar, - WEB-INF/lib/bcmail-*.jar, - WEB-INF/lib/bcprov-*.jar, - WEB-INF/lib/canl-*.jar, - WEB-INF/lib/voms-api-java-*.jar, - WEB-INF/lib/https-utils-*.jar, - WEB-INF/lib/org.apache.jasper.*.jar, - WEB-INF/lib/org.eclipse.jdt.core*.jar, - WEB-INF/lib/voms-container*.jar - - - - ${basedir}/src/main/resources - - voms-admin.tld - - - WEB-INF/classes/org/glite/security/voms/admin/jsp - - - - - - - org.mortbay.jetty - jetty-jspc-maven-plugin - - - jspc - - jspc - - - - - - - - maven-assembly-plugin - - - ${basedir}/src/assemble/tarball.xml - - voms-admin - - - - package - - single - - - - - - - - + ${struts.version} +
    + + + + org.opensaml + opensaml + ${opensaml.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + jcl-over-slf4j + + + org.slf4j + log4j-over-slf4j + + + org.slf4j + jul-to-slf4j + + + org.slf4j + jcl104-over-slf4j + + + org.bouncycastle + bcprov-ext-jdk15 + + + org.bouncycastle + bcprov-jdk15 + + + velocity + velocity + + + + + + + + org.slf4j + slf4j-api + + + + org.apache.logging.log4j + log4j-to-slf4j + ${log4j2.version} + + + + org.slf4j + log4j-over-slf4j + + + + org.slf4j + jcl-over-slf4j + + + + ch.qos.logback + logback-core + + + + ch.qos.logback + logback-classic + + + + org.italiangrid + https-utils + +
    + + + + EMI + + true + + + + / + /etc/voms-admin + voms + /usr/lib64/oracle/11.2.0.3.0/client/lib64 + /etc/voms + + + + + + maven-assembly-plugin + + + ${basedir}/src/assemble/tarball.xml + + voms-admin + + + + package + + single + + + + + + + + + + dev + + + /opt/voms/ + /opt/voms/etc/voms-admin + + /usr/lib64/oracle/11.2.0.3.0/client/lib64 + /opt/voms/etc/voms + + + + + prod + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + ${basedir}/target/web.xml + + + WEB-INF/classes/logback*.xml, + WEB-INF/lib/javax*.jar, + WEB-INF/lib/jetty-all-server*.jar, + WEB-INF/lib/jetty-jsp-*.jar, + WEB-INF/lib/bcmail-*.jar, + WEB-INF/lib/bcprov-*.jar, + WEB-INF/lib/canl-*.jar, + WEB-INF/lib/voms-api-java-*.jar, + WEB-INF/lib/https-utils-*.jar, + WEB-INF/lib/org.apache.jasper.*.jar, + WEB-INF/lib/org.eclipse.jdt.core*.jar, + WEB-INF/lib/voms-container*.jar + + + + ${basedir}/src/main/resources + + voms-admin.tld + + + WEB-INF/classes/org/glite/security/voms/admin/jsp + + + + + + + org.mortbay.jetty + jetty-jspc-maven-plugin + + + jspc + + jspc + + + + + + + + maven-assembly-plugin + + + ${basedir}/src/assemble/tarball.xml + + voms-admin + + + + package + + single + + + + + + + +
    diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 4e94a615..5492d887 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.8.0-SNAPSHOT + 3.8.0.rc0 voms-container From c5a2ec27865a137057a97087ba1d82d65a4d3858 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 24 Sep 2020 17:15:10 +0200 Subject: [PATCH 54/63] Better handling of some RDNs --- .../java/org/glite/security/voms/admin/taglib/FormatDNTag.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/taglib/FormatDNTag.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/taglib/FormatDNTag.java index bfb331c8..888c49a0 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/taglib/FormatDNTag.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/taglib/FormatDNTag.java @@ -41,7 +41,8 @@ public class FormatDNTag extends TagSupport { * FIXME: Should allow for more characters inside the fields, to be standard * compliant **/ - private static final String regexTemplate = "=((?:(?:\\/(?!DN|DC|STREET|O|OU|CN|C|L|E|Email|emailAddress|UID|uid))?\\w?:?;?'?\"?`?\\s?\\.?@?-?\\p{L}?\\(?\\)?,?)*)"; + private static final String regexTemplate = + "=((?:(?:\\/(?!DN|DC|street|postalCode|STREET|O|OU|CN|C|L|E|Email|emailAddress|UID|uid))?\\w?:?;?'?\"?`?\\s?\\.?@?-?\\p{L}?\\(?\\)?,?)*)"; private void write(String s) throws JspTagException { From 65b472405ec8598c74b10d013e051cc0f7fa14a6 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 26 Oct 2020 07:48:55 +0100 Subject: [PATCH 55/63] Bumped version to 3.8.0 --- compose/docker-compose.yml | 6 +- .../dev/centos7/setup/configure-vos.sh | 2 +- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 2 +- .../persistence/deployer/SchemaDeployer.java | 383 ++++++++---------- voms-container/pom.xml | 2 +- 7 files changed, 186 insertions(+), 213 deletions(-) diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index 015f4f3e..07143004 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -62,7 +62,7 @@ services: environment: # This is the VOMS Admin configuration # - VOMS_VO_COUNT: 0 # 0 creates 1 VO, 1 two VOs, ... + VOMS_VO_COUNT: 1 # 0 creates 1 VO, 1 two VOs, ... VOMS_HOSTNAME: dev.local.io MAILHOST: mail MYSQL_ROOT_PASSWORD: pwd @@ -82,9 +82,9 @@ services: # VOMS_UPGRADE_DB: y # VOMS_LOAD_DB_DUMP: y - # VOMS_DEV_MODE: y + VOMS_DEV_MODE: y - VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check --dburlparams useSSL=false&serverTimezone=Europe/Rome + VOMS_CONFIGURE_OPTIONS: --skip-ca-check --admin-skip-ca-check VOMS_ARGS: --war /code/voms-admin-server/target/voms-admin.war # ENABLE_YOURKIT: y diff --git a/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh b/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh index 4b8914ab..630b5db1 100644 --- a/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh +++ b/docker/voms-admin-server/dev/centos7/setup/configure-vos.sh @@ -15,7 +15,7 @@ configure_vo(){ --dbtype mysql \ --deploy-database \ --dbname ${VO_NAME} \ - --dbusername $VOMS_DB_USERNAME \ + --dbusername ${VOMS_DB_USERNAME} \ --dbpassword $VOMS_DB_PASSWORD \ --dbhost ${VOMS_MYSQL_HOST} \ --mail-from $VOMS_MAIL_FROM \ diff --git a/pom.xml b/pom.xml index 71342bea..170c582f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.italiangrid voms-admin-parent - 3.8.0.rc0 + 3.8.0 pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index 1d538a81..4ff37f37 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.8.0.rc0 + 3.8.0 voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 96959ad3..81dd5169 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -16,7 +16,7 @@ org.italiangrid voms-admin-parent - 3.8.0.rc0 + 3.8.0 voms-admin-server diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/deployer/SchemaDeployer.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/deployer/SchemaDeployer.java index 42db3efd..03b35ea2 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/deployer/SchemaDeployer.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/persistence/deployer/SchemaDeployer.java @@ -84,8 +84,7 @@ public class SchemaDeployer { public static final String ORACLE_PRODUCT_NAME = "Oracle"; public static final String MYSQL_PRODUCT_NAME = "MySQL"; - private static final Logger log = LoggerFactory - .getLogger(SchemaDeployer.class); + private static final Logger log = LoggerFactory.getLogger(SchemaDeployer.class); protected CommandLineParser parser = new PosixParser(); @@ -111,8 +110,7 @@ public class SchemaDeployer { Dialect dialect; - AuditLogHelper auditLogHelper = new AuditLogHelper( - CurrentAdminPrincipal.LOCAL_DB_PRINCIPAL); + AuditLogHelper auditLogHelper = new AuditLogHelper(CurrentAdminPrincipal.LOCAL_DB_PRINCIPAL); public SchemaDeployer(String[] args) { @@ -141,19 +139,18 @@ private void checkDatabaseConnectivity() { try { - s = HibernateFactory.getFactory() - .openSession(); + s = HibernateFactory.getFactory().openSession(); s.beginTransaction(); } catch (GenericJDBCException e) { log.error(""); log.error( - "==========================================================================================================================="); + "==========================================================================================================================="); log.error( - "Error connecting to the voms database! Check your database settings and ensure that the database backend is up and running."); + "Error connecting to the voms database! Check your database settings and ensure that the database backend is up and running."); log.error( - "============================================================================================================================"); + "============================================================================================================================"); if (log.isDebugEnabled()) log.error(e.getMessage(), e); @@ -177,8 +174,7 @@ private void checkDatabaseWritable() { try { - s = HibernateFactory.getFactory() - .openSession(); + s = HibernateFactory.getFactory().openSession(); Transaction t = s.beginTransaction(); s.createSQLQuery("create table writetest(integer a)"); @@ -191,17 +187,17 @@ private void checkDatabaseWritable() { } catch (Throwable t) { log.error( - "Error writing to the voms database. Check your database settings and that the database backend is up and running."); + "Error writing to the voms database. Check your database settings and that the database backend is up and running."); if (log.isDebugEnabled()) log.error( - "Error opening connection to the voms database. Check your database settings, or ensure that the local is up & running\nCause:" - + t.getMessage(), - t); + "Error opening connection to the voms database. Check your database settings, or ensure that the local is up & running\nCause:" + + t.getMessage(), + t); throw new VOMSDatabaseException( - "Error opening connection to the voms database. Check your database settings, or ensure that the local is up & running", - t); + "Error opening connection to the voms database. Check your database settings, or ensure that the local is up & running", + t); } finally { @@ -218,11 +214,11 @@ private void execute() { System.setProperty(VOMSConfigurationConstants.VO_NAME, vo); VOMSConfiguration.load(null); - boolean skipCaCheck = VOMSConfiguration.instance() - .getBoolean(VOMSConfigurationConstants.SKIP_CA_CHECK, false); + boolean skipCaCheck = + VOMSConfiguration.instance().getBoolean(VOMSConfigurationConstants.SKIP_CA_CHECK, false); LookupPolicyProvider.initialize(skipCaCheck); - + HibernateFactory.initialize(getHibernateMetadataSources()); if (command.equals("deploy")) @@ -274,23 +270,18 @@ private boolean isOracleBackend() { } catch (HibernateException e) { - log.error( - "Hibernate error accessing database metadata from Hibernate connection!", - e); + log.error("Hibernate error accessing database metadata from Hibernate connection!", e); System.exit(-1); } catch (SQLException e) { - log.error( - "SQL error while accessing database metadata from Hibernate connection!", - e); + log.error("SQL error while accessing database metadata from Hibernate connection!", e); System.exit(-1); } log.debug("Detected database: " + dbProductName); - return dbProductName.trim() - .equals(ORACLE_PRODUCT_NAME); + return dbProductName.trim().equals(ORACLE_PRODUCT_NAME); } @@ -355,10 +346,59 @@ private String getTimestampType() { } - private ResultSet getTableNamesMatchingPattern(DatabaseMetaData md, - String pattern) { + private void printSchemaNames(DatabaseMetaData md) { + + try { + + ResultSet schemas = md.getSchemas(); + boolean schemasFound = false; + + while (schemas.next()) { + schemasFound = true; + String schemaName = schemas.getString("TABLE_SCHEM"); + String schemaCatalog = schemas.getString("TABLE_CATALOG"); + + log.info("Schema: {}, Catalog: {}", schemaName, schemaCatalog); + } + + if (!schemasFound) { + log.info("No schemas found"); + } + + } catch (SQLException e) { + log.error("Error reading schema names from database metadata object!", e); + System.exit(-1); + } + + } + + private ResultSet getAllTableNames(DatabaseMetaData md) { + String[] names = {"TABLE"}; + + + ResultSet tableNames = null; + + try { + + String dbUrl = md.getURL(); + String dbName = dbUrl.substring(dbUrl.lastIndexOf('/') + 1); + + log.info("DB URL: {}. DB name: {}", dbUrl, dbName); + + tableNames = md.getTables(dbName, null, null, names); + + } catch (SQLException e) { + log.error("Error reading table names from database metadata object!", e); + System.exit(-1); + } + + return tableNames; + } + + + private ResultSet getTableNamesMatchingPattern(DatabaseMetaData md, String pattern) { - String[] names = { "TABLE" }; + String[] names = {"TABLE"}; ResultSet tableNames = null; @@ -389,14 +429,14 @@ private int checkDatabaseExistence() { } catch (Throwable e) { - log.error( - "Hibernate error accessing database metadata from Hibernate connection!", - e); + log.error("Hibernate error accessing database metadata from Hibernate connection!", e); System.exit(-1); } - ResultSet tableNames = getTableNamesMatchingPattern(dbMetadata, "%"); + printSchemaNames(dbMetadata); + + ResultSet tableNames = getAllTableNames(dbMetadata); boolean foundACL2 = false; boolean foundACL = false; @@ -450,9 +490,8 @@ private int checkDatabaseExistence() { private List parseUpgradeScript(String filename) throws IOException { - BufferedReader reader = new BufferedReader( - new InputStreamReader(this.getClass() - .getResourceAsStream(filename))); + BufferedReader reader = + new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream(filename))); ArrayList commands = new ArrayList(); @@ -489,14 +528,14 @@ private List loadUpgradeScriptToV6() throws IOException { private void fixMissingIndexesOnAuditTable() { - FixMissingIndexesOnAuditTable fixIndexes = new FixMissingIndexesOnAuditTable( - HibernateFactory.getSession()); + FixMissingIndexesOnAuditTable fixIndexes = + new FixMissingIndexesOnAuditTable(HibernateFactory.getSession()); fixIndexes.run(); } - - + + private boolean doUpgrateToV6() { final int existingDB = checkDatabaseExistence(); @@ -507,17 +546,13 @@ private boolean doUpgrateToV6() { } if (existingDB < 3) { - log.error("Upgrade not supported from this database version: {}", - existingDB); + log.error("Upgrade not supported from this database version: {}", existingDB); System.exit(-1); } if (existingDB == 3) { String versionToBeUpgraded = "5"; - String adminVersion = VOMSVersionDAO.instance() - .getVersion() - .getAdminVersion() - .trim(); + String adminVersion = VOMSVersionDAO.instance().getVersion().getAdminVersion().trim(); if (adminVersion.equals(SchemaVersion.VOMS_ADMIN_DB_VERSION)) { log.warn("No upgrade needed, found schema version {}", adminVersion); @@ -530,20 +565,17 @@ private boolean doUpgrateToV6() { } try { - - log.info("Upgrading database schema from version {} to version {}", - adminVersion, 6); + + log.info("Upgrading database schema from version {} to version {}", adminVersion, 6); List upgradeScript = loadUpgradeScriptToV6(); HibernateFactory.beginTransaction(); - UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork( - upgradeScript); + UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork(upgradeScript); try { - HibernateFactory.getSession() - .doWork(upgradeWork); + HibernateFactory.getSession().doWork(upgradeWork); } catch (Throwable t) { log.error("Error upgrading voms database!", t); HibernateFactory.rollbackTransaction(); @@ -551,14 +583,12 @@ private boolean doUpgrateToV6() { } // Update database version - VOMSVersionDAO.instance() - .setupVersion("6"); + VOMSVersionDAO.instance().setupVersion("6"); HibernateFactory.commitTransaction(); return true; } catch (Exception e) { - log.error("Error upgrading VOMS database to schema version 6: {}", - e.getMessage(), e); + log.error("Error upgrading VOMS database to schema version 6: {}", e.getMessage(), e); HibernateFactory.rollbackTransaction(); } } @@ -576,17 +606,13 @@ private boolean doUpgrateToV5() { } if (existingDB < 3) { - log.error("Upgrade not supported from this database version: {}", - existingDB); + log.error("Upgrade not supported from this database version: {}", existingDB); System.exit(-1); } if (existingDB == 3) { String versionToBeUpgraded = "4"; - String adminVersion = VOMSVersionDAO.instance() - .getVersion() - .getAdminVersion() - .trim(); + String adminVersion = VOMSVersionDAO.instance().getVersion().getAdminVersion().trim(); if (adminVersion.equals(SchemaVersion.VOMS_ADMIN_DB_VERSION)) { log.warn("No upgrade needed, found schema version {}", adminVersion); @@ -594,44 +620,38 @@ private boolean doUpgrateToV5() { } if (!adminVersion.equals(versionToBeUpgraded)) { - log.error("Upgrade to v5 not supported from schema version {}", - adminVersion); + log.error("Upgrade to v5 not supported from schema version {}", adminVersion); return false; } - - log.info("Upgrading database schema from version {} to version {}", - adminVersion, 5); + + log.info("Upgrading database schema from version {} to version {}", adminVersion, 5); try { List upgradeScript = loadUpgradeScriptToV5(); HibernateFactory.beginTransaction(); - - UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork( - upgradeScript); - + + UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork(upgradeScript); + try { - HibernateFactory.getSession() - .doWork(upgradeWork); + HibernateFactory.getSession().doWork(upgradeWork); } catch (Throwable t) { log.error("Error upgrading voms database!", t); HibernateFactory.rollbackTransaction(); System.exit(2); } - + fixMissingIndexesOnAuditTable(); // Update database version - VOMSVersionDAO.instance() - .setupVersion("5"); + VOMSVersionDAO.instance().setupVersion("5"); HibernateFactory.commitTransaction(); return true; } catch (Exception e) { - log.error("Error upgrading VOMS database to schema version 5: {}", - e.getMessage(), e); + log.error("Error upgrading VOMS database to schema version 5: {}", e.getMessage(), e); HibernateFactory.rollbackTransaction(); } } @@ -641,12 +661,8 @@ private boolean doUpgrateToV5() { private boolean doUpgradeToV4() { - String[] versionsToBeUpgraded = { "3.2.0", "3.3.0", "3.3.1", "3.3.2", - "3.3.3" }; - String adminVersion = VOMSVersionDAO.instance() - .getVersion() - .getAdminVersion() - .trim(); + String[] versionsToBeUpgraded = {"3.2.0", "3.3.0", "3.3.1", "3.3.2", "3.3.3"}; + String adminVersion = VOMSVersionDAO.instance().getVersion().getAdminVersion().trim(); if (adminVersion.equals(SchemaVersion.VOMS_ADMIN_DB_VERSION)) { log.warn("No upgrade needed, found schema version {}", adminVersion); @@ -657,9 +673,8 @@ private boolean doUpgradeToV4() { for (String v : versionsToBeUpgraded) { if (adminVersion.equals(v)) { - log.debug( - "Found VOMS Admin database version {} that requires a schema upgrade.", - adminVersion); + log.debug("Found VOMS Admin database version {} that requires a schema upgrade.", + adminVersion); upgradeSupported = true; break; } @@ -667,40 +682,34 @@ private boolean doUpgradeToV4() { if (!upgradeSupported) { - log.error("Upgrade to v4 not supported from schema version {}", - adminVersion); + log.error("Upgrade to v4 not supported from schema version {}", adminVersion); return false; } - log.info("Upgrading database schema from version {} to version {}", - adminVersion, "4"); + log.info("Upgrading database schema from version {} to version {}", adminVersion, "4"); try { List upgradeScript = loadUpgradeScriptToV4(); - - UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork( - upgradeScript); + + UpgradeDatabaseWork upgradeWork = new UpgradeDatabaseWork(upgradeScript); HibernateFactory.beginTransaction(); try { - HibernateFactory.getSession() - .doWork(upgradeWork); + HibernateFactory.getSession().doWork(upgradeWork); } catch (Throwable t) { log.error("Error upgrading voms database!", t); HibernateFactory.rollbackTransaction(); System.exit(2); } - + // Update database version - VOMSVersionDAO.instance() - .setupVersion("4"); + VOMSVersionDAO.instance().setupVersion("4"); HibernateFactory.commitTransaction(); return true; } catch (Exception e) { - log.error("Error upgrading VOMS database to schema version 4: {}", - e.getMessage(), e); + log.error("Error upgrading VOMS database to schema version 4: {}", e.getMessage(), e); HibernateFactory.rollbackTransaction(); } @@ -752,21 +761,17 @@ private void doRemoveAdmin() { try { - VOMSAdmin a = VOMSAdminDAO.instance() - .lookup(adminDN, adminCA); + VOMSAdmin a = VOMSAdminDAO.instance().lookup(adminDN, adminCA); if (a == null) { - log.info("Admin '" + adminDN + "," + adminCA - + "' does not exists in database..."); + log.info("Admin '" + adminDN + "," + adminCA + "' does not exists in database..."); return; } - List affectedACLs = ACLDAO.instance() - .deletePermissionsForAdmin(a); + List affectedACLs = ACLDAO.instance().deletePermissionsForAdmin(a); - VOMSAdminDAO.instance() - .delete(a); + VOMSAdminDAO.instance().delete(a); for (ACL acl : affectedACLs) { auditLogHelper.saveAuditEvent(ACLUpdatedEvent.class, acl); @@ -777,8 +782,7 @@ private void doRemoveAdmin() { HibernateFactory.commitTransaction(); log.info("Administrator '{},{}' removed", - new String[] { a.getDn(), a.getCa() - .getSubjectString() }); + new String[] {a.getDn(), a.getCa().getSubjectString()}); } catch (Throwable t) { @@ -799,59 +803,45 @@ private void doAddAdmin() { try { - VOMSAdmin a = VOMSAdminDAO.instance() - .lookup(adminDN, adminCA); + VOMSAdmin a = VOMSAdminDAO.instance().lookup(adminDN, adminCA); if (a != null) { - log.info("Admin '" + a.getDn() + "," + a.getCa() - .getDn() + "' already exists in database..."); - log.warn( - "This admin will be granted full privileges on the VOMS database."); + log.info( + "Admin '" + a.getDn() + "," + a.getCa().getDn() + "' already exists in database..."); + log.warn("This admin will be granted full privileges on the VOMS database."); } else { - log.info("Admin '" + adminDN + "," + adminCA - + "' not found. It will be created..."); + log.info("Admin '" + adminDN + "," + adminCA + "' not found. It will be created..."); // Admin does not exist, create it! - a = VOMSAdminDAO.instance() - .create(adminDN, adminCA, adminEmailAddress); + a = VOMSAdminDAO.instance().create(adminDN, adminCA, adminEmailAddress); auditLogHelper.saveAuditEvent(AdminCreatedEvent.class, a); } - Iterator i = VOMSGroupDAO.instance() - .findAll() - .iterator(); + Iterator i = VOMSGroupDAO.instance().findAll().iterator(); while (i.hasNext()) { VOMSGroup g = i.next(); - g.getACL() - .setPermissions(a, VOMSPermission.getAllPermissions()); + g.getACL().setPermissions(a, VOMSPermission.getAllPermissions()); log.info("Adding ALL permissions on '{}' for admin '{},{}'", - new String[] { g.toString(), a.getDn(), a.getCa() - .getSubjectString() }); + new String[] {g.toString(), a.getDn(), a.getCa().getSubjectString()}); - Iterator rolesIter = VOMSRoleDAO.instance() - .findAll() - .iterator(); + Iterator rolesIter = VOMSRoleDAO.instance().findAll().iterator(); while (rolesIter.hasNext()) { VOMSRole r = rolesIter.next(); - r.getACL(g) - .setPermissions(a, VOMSPermission.getAllPermissions()); + r.getACL(g).setPermissions(a, VOMSPermission.getAllPermissions()); log.info("Adding ALL permissions on role '{}/{}' for admin '{},{}'", - new String[] { g.toString(), r.toString(), a.getDn(), a.getCa() - .getSubjectString() }); + new String[] {g.toString(), r.toString(), a.getDn(), a.getCa().getSubjectString()}); - HibernateFactory.getSession() - .save(r); + HibernateFactory.getSession().save(r); auditLogHelper.saveAuditEvent(ACLUpdatedEvent.class, r.getACL(g)); } - HibernateFactory.getSession() - .save(g); + HibernateFactory.getSession().save(g); auditLogHelper.saveAuditEvent(ACLUpdatedEvent.class, g.getACL()); } @@ -869,11 +859,11 @@ private void doAddAdmin() { } private String getHibernateConfigurationFile(String vo) { - - return String.format("%s/%s/%s", getVOConfigurationDir(), vo, - "database.properties"); - + + return String.format("%s/%s/%s", getVOConfigurationDir(), vo, "database.properties"); + } + private String getVOConfigurationDir() { Properties sysconfProps = SysconfigUtil.loadSysconfig(); @@ -899,13 +889,12 @@ private boolean isVoConfigured(String voName) { return false; } - + private MetadataSources getHibernateMetadataSources() { - - StandardServiceRegistryBuilder registryBuilder = - new StandardServiceRegistryBuilder(); - - if (hibernatePropertiesFile == null){ + + StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder(); + + if (hibernatePropertiesFile == null) { registryBuilder.loadProperties(new File(getHibernateConfigurationFile(vo))); } else { registryBuilder.loadProperties(new File(hibernatePropertiesFile)); @@ -945,15 +934,15 @@ private void doUndeploy() { if (existingDB == 1) { log.error( - "This tool cannot undeploy voms-admin 1.2.x database! Please upgrade to voms-admin 2 or use voms-admin-configure 1.2.x tools to undeploy this database."); + "This tool cannot undeploy voms-admin 1.2.x database! Please upgrade to voms-admin 2 or use voms-admin-configure 1.2.x tools to undeploy this database."); System.exit(-1); } if (existingDB == 2) { log.error( - "This tool cannot undeploy voms-admin 2.0.x databases! Please either upgrade the database to voms-admin 2.5 (using this tool) or use voms-admin-configure 2.0.x" - + " tools to undeploy this database"); + "This tool cannot undeploy voms-admin 2.0.x databases! Please either upgrade the database to voms-admin 2.5 (using this tool) or use voms-admin-configure 2.0.x" + + " tools to undeploy this database"); System.exit(-1); } @@ -967,13 +956,13 @@ private void doUndeploy() { SchemaExport export = new SchemaExport(); export.setHaltOnError(true); - - + + EnumSet targetTypes = EnumSet.of(TargetType.DATABASE); Metadata md = getHibernateMetadataSources().getMetadataBuilder().build(); export.drop(targetTypes, md); - + @SuppressWarnings("rawtypes") List l = export.getExceptions(); @@ -1007,44 +996,34 @@ private void doGrantROAccess() { HibernateFactory.beginTransaction(); - VOMSAdmin anyUserAdmin = VOMSAdminDAO.instance() - .getAnyAuthenticatedUserAdmin(); + VOMSAdmin anyUserAdmin = VOMSAdminDAO.instance().getAnyAuthenticatedUserAdmin(); VOMSPermission readOnlyPerms = VOMSPermission.getEmptyPermissions() .setContainerReadPermission() .setMembershipReadPermission(); - List groups = VOMSGroupDAO.instance() - .findAll(); + List groups = VOMSGroupDAO.instance().findAll(); for (VOMSGroup g : groups) { - g.getACL() - .setPermissions(anyUserAdmin, readOnlyPerms); + g.getACL().setPermissions(anyUserAdmin, readOnlyPerms); - log.info( - "Granting read-only access to any authenticated user on group '{}'", - g.getName()); + log.info("Granting read-only access to any authenticated user on group '{}'", g.getName()); - List roles = VOMSRoleDAO.instance() - .findAll(); + List roles = VOMSRoleDAO.instance().findAll(); for (VOMSRole r : roles) { - r.getACL(g) - .setPermissions(anyUserAdmin, readOnlyPerms); - log.info( - "Granting read-only access to any authenticated user on role '{}/{}'", - new String[] { g.toString(), r.toString() }); + r.getACL(g).setPermissions(anyUserAdmin, readOnlyPerms); + log.info("Granting read-only access to any authenticated user on role '{}/{}'", + new String[] {g.toString(), r.toString()}); - HibernateFactory.getSession() - .save(r); + HibernateFactory.getSession().save(r); auditLogHelper.saveAuditEvent(ACLUpdatedEvent.class, r.getACL(g)); } - HibernateFactory.getSession() - .save(g); + HibernateFactory.getSession().save(g); auditLogHelper.saveAuditEvent(ACLUpdatedEvent.class, g.getACL()); } @@ -1067,11 +1046,9 @@ private void doDeploy() { int existingDb = checkDatabaseExistence(); if (existingDb > 0) { - final String adminDbVersion = VOMSVersionDAO - .instance().getVersion().getAdminVersion().trim(); - - log - .warn("Existing voms database found. Will not overwrite " + final String adminDbVersion = VOMSVersionDAO.instance().getVersion().getAdminVersion().trim(); + + log.warn("Existing voms database found. Will not overwrite " + "the database! (admin db version: {})", adminDbVersion); System.exit(0); } @@ -1079,7 +1056,7 @@ private void doDeploy() { checkDatabaseWritable(); SchemaExport exporter = new SchemaExport(); - + EnumSet targetTypes = EnumSet.of(TargetType.DATABASE); exporter.createOnly(targetTypes, HibernateFactory.getMetadata()); @@ -1094,19 +1071,19 @@ private void doDeploy() { System.exit(2); } - + // This is needed as the version of hibernate we are using // does not support defining indexes on join table columns // See: https://hibernate.atlassian.net/browse/HHH-4263 - CreateAuditEventDataIndexes createIndexTask = new CreateAuditEventDataIndexes( - HibernateFactory.getSession()); + CreateAuditEventDataIndexes createIndexTask = + new CreateAuditEventDataIndexes(HibernateFactory.getSession()); HibernateFactory.beginTransaction(); - + createIndexTask.run(); - CreateAttributeValueIndex avIndexTask = new CreateAttributeValueIndex( - HibernateFactory.getSession()); + CreateAttributeValueIndex avIndexTask = + new CreateAttributeValueIndex(HibernateFactory.getSession()); avIndexTask.run(); @@ -1125,13 +1102,11 @@ protected void setupCLParser() { options = new Options(); - options.addOption(OptionBuilder.withLongOpt("help") - .withDescription("Displays helps and exits.") - .create("h")); + options.addOption( + OptionBuilder.withLongOpt("help").withDescription("Displays helps and exits.").create("h")); options.addOption(OptionBuilder.withLongOpt("command") - .withDescription( - "Specifies the command to be executed: deploy,undeploy,upgrade,add-admin") + .withDescription("Specifies the command to be executed: deploy,undeploy,upgrade,add-admin") .hasArg() .create("command")); @@ -1152,19 +1127,19 @@ protected void setupCLParser() { options.addOption(OptionBuilder.withLongOpt("dn") .withDescription( - "Specifies the dn for the admin to add (valid only if add-admin command is given).") + "Specifies the dn for the admin to add (valid only if add-admin command is given).") .hasArg() .create("dn")); options.addOption(OptionBuilder.withLongOpt("ca") .withDescription( - "Specifies the ca for the admin to add (valid only if add-admin command is given).") + "Specifies the ca for the admin to add (valid only if add-admin command is given).") .hasArg() .create("ca")); options.addOption(OptionBuilder.withLongOpt("email") .withDescription( - "Specifies the email address for the admin to add (valid only if add-admin command is given).") + "Specifies the email address for the admin to add (valid only if add-admin command is given).") .hasArg() .create("email")); @@ -1195,11 +1170,10 @@ protected void checkArguments(String[] args) { command = line.getOptionValue("command"); // FIXME: use an Enumeration for the commands!! - if (!command.equals("deploy") && !command.equals("upgrade") - && !command.equals("add-admin") && !command.equals("remove-admin") - && !command.equals("undeploy") && !command.equals("upgrade-script") - && !command.equals("check-connectivity") - && !command.equals("grant-read-only-access")) { + if (!command.equals("deploy") && !command.equals("upgrade") && !command.equals("add-admin") + && !command.equals("remove-admin") && !command.equals("undeploy") + && !command.equals("upgrade-script") && !command.equals("check-connectivity") + && !command.equals("grant-read-only-access")) { System.err.println("Unknown command specified: " + command); printHelpMessageAndExit(2); @@ -1224,8 +1198,7 @@ protected void checkArguments(String[] args) { } catch (ParseException e) { - throw new VOMSException( - "Error parsing command-line arguments: " + e.getMessage(), e); + throw new VOMSException("Error parsing command-line arguments: " + e.getMessage(), e); } diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 5492d887..a6d65f59 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.8.0.rc0 + 3.8.0 voms-container From 6779ec27444426ffeb767f3bb96b463e9973a035 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 26 Oct 2020 07:51:29 +0100 Subject: [PATCH 56/63] Bump junit from 4.11 to 4.13.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 170c582f..8aae3fb4 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ UTF-8 - 4.11 + 4.13.1 1.3 2.0.5-beta 1.7.29 From 47b6a9c3069b66463c67970081342ce1a8fe7171 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Mon, 26 Oct 2020 07:57:27 +0100 Subject: [PATCH 57/63] Fixed license header --- voms-admin-server/pom.xml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 81dd5169..e9fe98d7 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -1,12 +1,21 @@ - + = 0 && startHour < 24) { - config.getMembesrshipCheck() + config.getMembershipCheck() .setStartHour( (Integer.parseInt(properties.getProperty(MEMBERSHIP_CHECK_START_HOUR_KEY)))); } } if (properties.containsKey(MEMBERSHIP_CHECK_RUN_AT_STARTUP_KEY)) { - config.getMembesrshipCheck() + config.getMembershipCheck() .setRunAtStartup( Boolean.parseBoolean(properties.getProperty(MEMBERSHIP_CHECK_RUN_AT_STARTUP_KEY))); } if (properties.containsKey(MEMBERSHIP_CHECK_PERIOD_KEY)) { - config.getMembesrshipCheck() + config.getMembershipCheck() .setPeriodInSeconds(Long.parseLong(properties.getProperty(MEMBERSHIP_CHECK_PERIOD_KEY))); } if (properties.containsKey(MEMBERSHIP_CHECK_ENABLED_KEY)) { - config.getMembesrshipCheck().setEnabled(Boolean.parseBoolean(MEMBERSHIP_CHECK_ENABLED_KEY)); + config.getMembershipCheck().setEnabled(Boolean.parseBoolean(MEMBERSHIP_CHECK_ENABLED_KEY)); } config.getApi().setEndpoint(properties.getProperty(API_ENDPOINT_KEY)); diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java index d0aeecdc..b4eccbe6 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java @@ -137,7 +137,7 @@ public void testMembershipCheckTaskScheduling() throws VOMSPluginConfigurationEx configurator.configure(); verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), - Mockito.anyLong(), Mockito.eq(props.getMembesrshipCheck().getPeriodInSeconds()), + Mockito.anyLong(), Mockito.eq(props.getMembershipCheck().getPeriodInSeconds()), Mockito.eq(TimeUnit.SECONDS)); verify(executorService).schedule(Mockito.isA(DatabaseTransactionTaskWrapper.class), @@ -148,13 +148,13 @@ public void testMembershipCheckTaskScheduling() throws VOMSPluginConfigurationEx public void testNoStartupTaskScheduling() throws VOMSPluginConfigurationException { HrDbProperties props = new HrDbProperties(); - props.getMembesrshipCheck().setRunAtStartup(false); + props.getMembershipCheck().setRunAtStartup(false); configurator.setHrConfig(props); configurator.configure(); verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), - Mockito.eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + Mockito.eq(props.getMembershipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); } @@ -163,7 +163,7 @@ public void testNoStartupTaskScheduling() throws VOMSPluginConfigurationExceptio public void testStartupTaskSchedulingCanceled() throws VOMSPluginConfigurationException { HrDbProperties props = new HrDbProperties(); - props.getMembesrshipCheck().setRunAtStartup(true); + props.getMembershipCheck().setRunAtStartup(true); configurator.setHrConfig(props); configurator.setClock(fixed(Instant.parse("2019-01-01T21:45:00.00Z"), ZoneId.systemDefault())); @@ -171,7 +171,7 @@ public void testStartupTaskSchedulingCanceled() throws VOMSPluginConfigurationEx verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), - eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + eq(props.getMembershipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); } @@ -180,8 +180,8 @@ public void testStartupTaskSchedulingCanceled() throws VOMSPluginConfigurationEx public void testStartupTaskScheduledTheNextDay() throws VOMSPluginConfigurationException { HrDbProperties props = new HrDbProperties(); - props.getMembesrshipCheck().setRunAtStartup(false); - props.getMembesrshipCheck().setStartHour(22); + props.getMembershipCheck().setRunAtStartup(false); + props.getMembershipCheck().setStartHour(22); configurator.setHrConfig(props); configurator.setClock(fixed(Instant.parse("2019-01-01T21:01:00.00Z"), ZoneId.systemDefault())); @@ -189,7 +189,7 @@ public void testStartupTaskScheduledTheNextDay() throws VOMSPluginConfigurationE verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), anyLong(), - eq(props.getMembesrshipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); + eq(props.getMembershipCheck().getPeriodInSeconds()), eq(TimeUnit.SECONDS)); verify(executorService, never()).schedule(isA(DatabaseTransactionTaskWrapper.class), anyLong(), any()); } diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java index ee3494b0..53fca7f3 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java @@ -67,8 +67,8 @@ public void testValueParsing() { assertThat(hrConfig.getApi().getEndpoint(), is("http://example")); assertThat(hrConfig.getApi().getUsername(), is("test")); assertThat(hrConfig.getApi().getPassword(), is("password")); - assertThat(hrConfig.getMembesrshipCheck().isEnabled(), is(false)); - assertThat(hrConfig.getMembesrshipCheck().getPeriodInSeconds(), is(86400L)); + assertThat(hrConfig.getMembershipCheck().isEnabled(), is(false)); + assertThat(hrConfig.getMembershipCheck().getPeriodInSeconds(), is(86400L)); } @Test diff --git a/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java index f5b80185..7b67547e 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDefaultHandlerTest.java @@ -15,9 +15,10 @@ */ package integration.hr; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.verify; import java.util.Date; @@ -210,8 +211,6 @@ public void testRestoreSuspendedUserDueToValidationError() { assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); verify(manager).restoreUser(Mockito.eq(user)); - - } @Test @@ -234,8 +233,34 @@ public void testRestoreSuspendedUserDueToMembershipExpiration() { assertThat(user.getEmailAddress(), is("TEST.USER@CNAF.INFN.IT".toLowerCase())); verify(manager).restoreUser(Mockito.eq(user)); + } + + @Test + public void testInstituteChangeHandling() { - + InstituteDTO firstInstitute = new InstituteDTO(); + institute.setName("First institute"); + + InstituteDTO secondInstitute = new InstituteDTO(); + institute.setName("Second institute"); + + oneParticipation.setExperiment("experiment"); + oneParticipation.setInstitute(firstInstitute); + oneParticipation.setStartDate(Date.from(ONE_YEAR_AGO)); + oneParticipation.setEndDate(Date.from(ONE_WEEK_AGO)); + + anotherParticipation.setExperiment("experiment"); + anotherParticipation.setInstitute(secondInstitute); + anotherParticipation.setStartDate(Date.from(A_DAY_AGO)); + + voPerson.setParticipations(Sets.newHashSet(oneParticipation, anotherParticipation)); + + user.setSuspended(true); + user.setSuspensionReasonCode(SuspensionReason.MEMBERSHIP_EXPIRATION); + user.setSuspensionReason(SuspensionReason.MEMBERSHIP_EXPIRATION.getMessage()); + + handler.synchronizeMembershipInformation(user, voPerson); + verify(manager).restoreUser(Mockito.eq(user)); } From c13d55c667e546d1e5b55d9b2db0c16563ddbb3f Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 10 Nov 2020 17:54:38 +0100 Subject: [PATCH 59/63] Bumped version to 3.8.1-SNAPSHOT --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 2 +- voms-container/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index c9d72cab..09f1281a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ voms-admin-parent - 3.8.0 + 3.8.1-SNAPSHOT pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index 4ff37f37..30ce6c6d 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.8.0 + 3.8.1-SNAPSHOT voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index ef6f6949..5e250fe8 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -26,7 +26,7 @@ org.italiangrid voms-admin-parent - 3.8.0 + 3.8.1-SNAPSHOT voms-admin-server diff --git a/voms-container/pom.xml b/voms-container/pom.xml index a6d65f59..736d590e 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.8.0 + 3.8.1-SNAPSHOT voms-container From 850f9e3bc992da77bdd73c08464f4dd0047f221f Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 10 Nov 2020 18:35:59 +0100 Subject: [PATCH 60/63] Fix hr.properties parsing Fix buggy `membership_check.enabled` property parsing. Issue: https://issues.infn.it/jira/browse/VOMS-883 --- .../integration/cern/HrDbProperties.java | 3 +- .../integration/hr/HrDbConfiguratorTests.java | 30 +++++++++++++++---- .../integration/hr/HrDbPropertiesTest.java | 6 ++++ .../hr.properties} | 0 .../resources/cern/enabled-task/hr.properties | 8 +++++ 5 files changed, 40 insertions(+), 7 deletions(-) rename voms-admin-server/src/test/resources/cern/{config/orgdb.properties => disabled-task/hr.properties} (100%) create mode 100644 voms-admin-server/src/test/resources/cern/enabled-task/hr.properties diff --git a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java index 91cdc645..0ca06762 100644 --- a/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java +++ b/voms-admin-server/src/main/java/org/glite/security/voms/admin/integration/cern/HrDbProperties.java @@ -187,7 +187,8 @@ public static final HrDbProperties fromProperties(Properties properties) { } if (properties.containsKey(MEMBERSHIP_CHECK_ENABLED_KEY)) { - config.getMembershipCheck().setEnabled(Boolean.parseBoolean(MEMBERSHIP_CHECK_ENABLED_KEY)); + config.getMembershipCheck() + .setEnabled(Boolean.parseBoolean(properties.getProperty(MEMBERSHIP_CHECK_ENABLED_KEY))); } config.getApi().setEndpoint(properties.getProperty(API_ENDPOINT_KEY)); diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java index b4eccbe6..59543dc5 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbConfiguratorTests.java @@ -99,19 +99,37 @@ public void setup() { configurator.setUserDao(dao); configurator.setClock(CLOCK); - when(vomsConfig.getConfigurationDirectoryPath()).thenReturn("src/test/resources/cern/config"); - when(vomsConfig.getExternalValidatorProperty(eq("orgdb"), anyString(), anyString())) - .thenReturn("src/test/resources/cern/config/orgdb.properties"); + when(vomsConfig.getConfigurationDirectoryPath()) + .thenReturn("src/test/resources/cern/disabled-task"); + when(vomsConfig.getExternalValidatorProperty(eq("orgdb"), eq("configFile"), anyString())) + .thenReturn("src/test/resources/cern/disabled-task/hr.properties"); when(apiFactory.newHrDbApiService(any())).thenReturn(api); when(validatorFactory.newHrDbRequestValidator(any(), any())).thenReturn(validator); when(syncTaskFactory.buildSyncTask(any(), any(), any(), any())).thenReturn(syncTask); } @Test - public void testConfigurationFileIsFoundAndParsed() throws VOMSPluginConfigurationException { + public void testDisabledConfigurationFileIsFoundAndParsed() + throws VOMSPluginConfigurationException { + configurator.configure(); + verifyZeroInteractions(executorService);// no interactions as periodic sync is disabled + verifyZeroInteractions(syncTaskFactory);// no interactions as periodic sync is disabled + verify(manager).setRequestValidationContext(Mockito.eq(validator)); + } + + @Test + public void testEnabledConfigurationFileIsFoundAndParsed() + throws VOMSPluginConfigurationException { + when(vomsConfig.getConfigurationDirectoryPath()) + .thenReturn("src/test/resources/cern/enabled-task"); + when(vomsConfig.getExternalValidatorProperty(eq("orgdb"), eq("configFile"), anyString())) + .thenReturn("src/test/resources/cern/enabled-task/hr.properties"); configurator.configure(); - verifyZeroInteractions(executorService); - verifyZeroInteractions(syncTaskFactory); + + verify(executorService).scheduleAtFixedRate(isA(DatabaseTransactionTaskWrapper.class), + Mockito.anyLong(), Mockito.eq(TimeUnit.HOURS.toSeconds(12)), + Mockito.eq(TimeUnit.SECONDS)); + verify(manager).setRequestValidationContext(Mockito.eq(validator)); } diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java index 53fca7f3..3ce72f94 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java @@ -71,6 +71,12 @@ public void testValueParsing() { assertThat(hrConfig.getMembershipCheck().getPeriodInSeconds(), is(86400L)); } + + @Test + public void testFileParsing() { + + } + @Test public void testApiTimeoutChecks() { Properties props = new Properties(); diff --git a/voms-admin-server/src/test/resources/cern/config/orgdb.properties b/voms-admin-server/src/test/resources/cern/disabled-task/hr.properties similarity index 100% rename from voms-admin-server/src/test/resources/cern/config/orgdb.properties rename to voms-admin-server/src/test/resources/cern/disabled-task/hr.properties diff --git a/voms-admin-server/src/test/resources/cern/enabled-task/hr.properties b/voms-admin-server/src/test/resources/cern/enabled-task/hr.properties new file mode 100644 index 00000000..6556749f --- /dev/null +++ b/voms-admin-server/src/test/resources/cern/enabled-task/hr.properties @@ -0,0 +1,8 @@ + experiment=cms + membership_check.enabled=true + membership_check.start_hour=4 + membership_check.run_at_startup=false + api.endpoint=http://localhost:8080 + api.username=user + api.password=password + api.timeout_secs=2 \ No newline at end of file From 5fa1ad5d3e341b79df37211a130994a9e1aa091f Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Tue, 10 Nov 2020 18:45:03 +0100 Subject: [PATCH 61/63] More HR properties parsing tests --- .../integration/hr/HrDbPropertiesTest.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java index 3ce72f94..c8facff9 100644 --- a/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java +++ b/voms-admin-server/src/test/java/integration/hr/HrDbPropertiesTest.java @@ -17,9 +17,13 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.Properties; import org.glite.security.voms.admin.integration.cern.HrDbError; @@ -73,7 +77,24 @@ public void testValueParsing() { @Test - public void testFileParsing() { + public void testFileParsing() throws FileNotFoundException, IOException { + + Properties props = new Properties(); + props + .load(new FileInputStream(new File("src/test/resources/cern/enabled-task/hr.properties"))); + + HrDbProperties hrDbProps = HrDbProperties.fromProperties(props); + + assertThat(hrDbProps.getExperimentName(), is("cms")); + assertThat(hrDbProps.getMembershipCheck().isEnabled(), is(true)); + assertThat(hrDbProps.getMembershipCheck().getStartHour(), is(4)); + assertThat(hrDbProps.getMembershipCheck().isRunAtStartup(), is(false)); + assertThat(hrDbProps.getApi().getEndpoint(), is("http://localhost:8080")); + assertThat(hrDbProps.getApi().getUsername(), is("user")); + assertThat(hrDbProps.getApi().getPassword(), is("password")); + assertThat(hrDbProps.getApi().getTimeoutInSeconds(), is(2L)); + + } From 884e70ae290e19a8f4f80ff1c200aa31990108d0 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Thu, 10 Dec 2020 18:28:15 +0100 Subject: [PATCH 62/63] Bump struts version to 2.5.26 --- voms-admin-server/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index 5e250fe8..ad57aa5d 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -38,7 +38,7 @@ ${project.version} 2.0.2 - 2.5.22 + 2.5.26 2.5.2 4.0.3 5.2.17.Final From 388a9ef334c82a445eebe87d61b1f8e88c6fa892 Mon Sep 17 00:00:00 2001 From: Andrea Ceccanti Date: Wed, 7 Apr 2021 18:41:43 +0200 Subject: [PATCH 63/63] Bumped version to 3.8.1 --- pom.xml | 2 +- voms-admin-api/pom.xml | 2 +- voms-admin-server/pom.xml | 2 +- voms-container/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 09f1281a..47934cdc 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ voms-admin-parent - 3.8.1-SNAPSHOT + 3.8.1 pom VOMS Admin Parent POM diff --git a/voms-admin-api/pom.xml b/voms-admin-api/pom.xml index 30ce6c6d..deabe256 100644 --- a/voms-admin-api/pom.xml +++ b/voms-admin-api/pom.xml @@ -5,7 +5,7 @@ org.italiangrid voms-admin-parent - 3.8.1-SNAPSHOT + 3.8.1 voms-admin-api diff --git a/voms-admin-server/pom.xml b/voms-admin-server/pom.xml index ad57aa5d..ed0b8667 100644 --- a/voms-admin-server/pom.xml +++ b/voms-admin-server/pom.xml @@ -26,7 +26,7 @@ org.italiangrid voms-admin-parent - 3.8.1-SNAPSHOT + 3.8.1 voms-admin-server diff --git a/voms-container/pom.xml b/voms-container/pom.xml index 736d590e..39b6ecaa 100644 --- a/voms-container/pom.xml +++ b/voms-container/pom.xml @@ -23,7 +23,7 @@ org.italiangrid voms-admin-parent - 3.8.1-SNAPSHOT + 3.8.1 voms-container