Skip to content

Commit 59cc9ff

Browse files
committed
Merge branch 'jira-wdt-939-cert-mgmt' into 'main'
Add plugin deployments and certificate management See merge request weblogic-cloud/weblogic-deploy-tooling!1819
2 parents c6d0d99 + 4095680 commit 59cc9ff

File tree

25 files changed

+836
-450
lines changed

25 files changed

+836
-450
lines changed

core/src/main/java/oracle/weblogic/deploy/util/WLSDeployArchive.java

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ public class WLSDeployArchive {
125125
*/
126126
public static final String ARCHIVE_SHLIBS_TARGET_DIR = WLSDPLY_ARCHIVE_BINARY_DIR + ZIP_SEP + "sharedLibraries";
127127

128+
/**
129+
* Top-level archive subdirectory where the plugins are stored and the subdirectory to
130+
* which they will be extracted.
131+
*/
132+
public static final String ARCHIVE_PLUGINS_TARGET_DIR = WLSDPLY_ARCHIVE_BINARY_DIR + ZIP_SEP + "pluginDeployments";
133+
128134
/**
129135
* Top-level archive subdirectory where the $DOMAIN_HOME/lib are stored.
130136
*/
@@ -212,6 +218,7 @@ public enum ArchiveEntryType {
212218
MIME_MAPPING,
213219
NODE_MANAGER_KEY_STORE,
214220
OPSS_WALLET,
221+
PLUGIN_DEPLOYMENT,
215222
RCU_WALLET,
216223
SAML2_DATA,
217224
SCRIPT,
@@ -340,6 +347,10 @@ public static String getPathForType(ArchiveEntryType type) {
340347
pathPrefix = ARCHIVE_SHLIBS_TARGET_DIR + ZIP_SEP;
341348
break;
342349

350+
case PLUGIN_DEPLOYMENT:
351+
pathPrefix = ARCHIVE_PLUGINS_TARGET_DIR + ZIP_SEP;
352+
break;
353+
343354
case STRUCTURED_APPLICATION:
344355
pathPrefix = ARCHIVE_STRUCT_APPS_TARGET_DIR + ZIP_SEP;
345356
break;
@@ -1052,6 +1063,152 @@ public void close() {
10521063
// methods using archiveType //
10531064
///////////////////////////////////////////////////////////////////////////////////////////////
10541065

1066+
/**
1067+
* Get the path of the archive entry as if it is in the archive file.
1068+
* This does not reconcile duplicate names and other items that require the archive file
1069+
* and is only used with discoverDomain -remote to give the user an archive path.
1070+
* @param archiveType the type of the entry
1071+
* @param path the original path of the entry
1072+
* @return name for model archive file name
1073+
*/
1074+
public static String getArchivePath(ArchiveEntryType archiveType, String path) {
1075+
String pathPrefix = getPathForType(archiveType);
1076+
return getArchiveName(pathPrefix, path);
1077+
}
1078+
1079+
public String addItem(ArchiveEntryType archiveType, String sourcePath) throws WLSDeployArchiveIOException {
1080+
final String METHOD = "addItem";
1081+
LOGGER.entering(CLASS, METHOD, archiveType, sourcePath);
1082+
1083+
File filePath = FileUtils.getCanonicalFile(sourcePath);
1084+
validateExistingFile(filePath, "path", getArchiveFileName(), METHOD, true);
1085+
1086+
String pathPrefix = getPathForType(archiveType);
1087+
String newName = addItemToZip(pathPrefix, filePath);
1088+
1089+
LOGGER.exiting(CLASS, METHOD, newName);
1090+
return newName;
1091+
}
1092+
1093+
public String replaceItem(ArchiveEntryType archiveType, String archiveName, String sourcePath)
1094+
throws WLSDeployArchiveIOException {
1095+
1096+
final String METHOD = "replaceItem";
1097+
LOGGER.entering(CLASS, METHOD, archiveType, archiveName, sourcePath);
1098+
1099+
String pathPrefix = getPathForType(archiveType);
1100+
String archivePath;
1101+
if (archiveName.startsWith(pathPrefix)) {
1102+
archivePath = archiveName;
1103+
} else {
1104+
archivePath = pathPrefix + archiveName;
1105+
}
1106+
1107+
getZipFile().removeZipEntries(archivePath);
1108+
String newName = addItem(archiveType, sourcePath);
1109+
1110+
LOGGER.exiting(CLASS, METHOD, newName);
1111+
return newName;
1112+
}
1113+
1114+
/**
1115+
* Extracts the named file or directory from the archive into the specified directory,
1116+
* preserving any archive directory structure.
1117+
*
1118+
* @param archiveType the type of the entry
1119+
* @param path the path of the file or directory in the archive
1120+
* @param directory the existing target directory (usually domain home)
1121+
* @throws WLSDeployArchiveIOException if an IOException occurred while reading the archive or writing the file
1122+
* @throws IllegalArgumentException if the directory does not exist or the path is empty
1123+
*/
1124+
public void extractItem(ArchiveEntryType archiveType, String path, File directory)
1125+
throws WLSDeployArchiveIOException {
1126+
1127+
final String METHOD = "extractItem";
1128+
LOGGER.entering(CLASS, METHOD, archiveType, path);
1129+
1130+
validateNonEmptyString(path, "path", METHOD);
1131+
validateExistingDirectory(directory, "directory", getArchiveFileName(), METHOD);
1132+
1133+
String pathPrefix = getPathForType(archiveType);
1134+
String archivePath = path;
1135+
if (!path.startsWith(pathPrefix)) {
1136+
archivePath = pathPrefix + path;
1137+
}
1138+
1139+
archivePath = fixupPathForDirectories(archivePath);
1140+
if (archivePath.endsWith(ZIP_SEP)) {
1141+
extractDirectoryFromZip(archivePath, directory);
1142+
} else {
1143+
extractFileFromZip(archivePath, directory);
1144+
}
1145+
1146+
LOGGER.exiting(CLASS, METHOD);
1147+
}
1148+
1149+
/**
1150+
* Remove the named item from the archive file. If this is the only entry
1151+
* in the archive file directory, the directory entry will also be removed, if present.
1152+
*
1153+
* @param path The item name (e.g., foo.jar) or the archive path
1154+
* to it (e.g., wlsdeploy/domainLibraries/foo.jar)
1155+
* @return the number of zip entries removed from the archive
1156+
* @throws WLSDeployArchiveIOException if the item is not present or an IOException occurred while
1157+
* reading the archive or writing the file
1158+
* @throws IllegalArgumentException if the path is null or empty
1159+
*/
1160+
public int removeItem(ArchiveEntryType archiveType, String path) throws WLSDeployArchiveIOException {
1161+
return removeItem(archiveType, path, false);
1162+
}
1163+
1164+
/**
1165+
* Remove the named item from the archive file. If this is the only entry
1166+
* in the archive file directory, the directory entry will also be removed, if present.
1167+
*
1168+
* @param path The item name (e.g., foo.jar) or the archive path
1169+
* to it (e.g., wlsdeploy/domainLibraries/foo.jar)
1170+
* @param silent If false, a WLSDeployArchiveIOException is thrown if the named item does not exist
1171+
* @return the number of zip entries removed from the archive
1172+
* @throws WLSDeployArchiveIOException if the item is not present (and silent = false) or an IOException
1173+
* occurred while reading the archive or writing the file
1174+
* @throws IllegalArgumentException if the path is null or empty
1175+
*/
1176+
public int removeItem(ArchiveEntryType archiveType, String path, boolean silent) throws WLSDeployArchiveIOException {
1177+
final String METHOD = "removeItem";
1178+
LOGGER.entering(CLASS, METHOD, path, silent);
1179+
1180+
validateNonEmptyString(path, "path", METHOD);
1181+
1182+
String pathPrefix = getPathForType(archiveType);
1183+
String archivePath;
1184+
String itemName;
1185+
if (path.startsWith(pathPrefix)) {
1186+
archivePath = path;
1187+
itemName = getNameFromPath(archivePath, pathPrefix.length() + 1);
1188+
} else {
1189+
archivePath = pathPrefix + path;
1190+
itemName = path;
1191+
}
1192+
1193+
List<String> zipEntries = getArchiveEntries(archiveType, itemName);
1194+
1195+
if (!silent && zipEntries.isEmpty()) {
1196+
WLSDeployArchiveIOException ex =
1197+
new WLSDeployArchiveIOException("WLSDPLY-01480", archiveType, itemName, getArchiveFileName(), archivePath);
1198+
LOGGER.throwing(CLASS, METHOD, ex);
1199+
throw ex;
1200+
}
1201+
1202+
int result = zipEntries.size();
1203+
for (String zipEntry : zipEntries) {
1204+
getZipFile().removeZipEntry(zipEntry);
1205+
}
1206+
result += removeEmptyTypeDir(archiveType, pathPrefix);
1207+
1208+
LOGGER.exiting(CLASS, METHOD, result);
1209+
return result;
1210+
}
1211+
10551212
/**
10561213
* Add a source file for the specified archive type, including an entry name.
10571214
* Example: config/wlsdeploy/servers/myServer/identity.jks

core/src/main/python/deploy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2017, 2024, Oracle and/or its affiliates.
2+
Copyright (c) 2017, 2025, Oracle and/or its affiliates.
33
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
44
55
The entry point for the deployApps tool.
@@ -165,6 +165,7 @@ def __deploy_online(model_deployer, model_context):
165165
__logger.info("WLSDPLY-09007", admin_url, method_name=_method_name, class_name=_class_name)
166166

167167
try:
168+
model_deployer.deploy_plugins()
168169
model_deployer.deploy_resources()
169170
model_deployer.distribute_database_wallets_online()
170171
model_deployer.deploy_app_attributes_online()
@@ -202,6 +203,7 @@ def __deploy_offline(model_deployer, model_context):
202203

203204
__wlst_helper.read_domain(domain_home)
204205

206+
model_deployer.deploy_plugins()
205207
model_deployer.deploy_model_offline()
206208

207209
try:

core/src/main/python/update.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (c) 2017, 2024, Oracle and/or its affiliates.
2+
Copyright (c) 2017, 2025, Oracle and/or its affiliates.
33
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
44
55
The entry point for the updateDomain tool.
@@ -192,6 +192,7 @@ def __update_online(model_deployer, model, model_context, aliases):
192192

193193
topology_updater.clear_placeholder_targeting(jdbc_names)
194194
topology_updater.update_nm_properties() # alias will skip for online, but log the omission
195+
model_deployer.deploy_plugins() # may be referenced in SecurityConfiguration/CertificateManagement
195196
topology_updater.update()
196197
model_deployer.deploy_resources()
197198
model_deployer.distribute_database_wallets_online()
@@ -251,6 +252,8 @@ def __update_offline(model_deployer, model, model_context, aliases):
251252

252253
topology_updater.set_server_groups()
253254
topology_updater.clear_placeholder_targeting(jdbc_names)
255+
256+
model_deployer.deploy_plugins() # may be referenced in SecurityConfiguration/CertificateManagement
254257
topology_updater.update()
255258

256259
# Add resources after server groups are established to prevent auto-renaming

core/src/main/python/wlsdeploy/aliases/alias_entries.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@
6161
from wlsdeploy.aliases.model_constants import HEALTH_SCORE
6262
from wlsdeploy.aliases.model_constants import JOLT_CONNECTION_POOL
6363
from wlsdeploy.aliases.model_constants import JPA
64+
from wlsdeploy.aliases.model_constants import LIBRARY
6465
from wlsdeploy.aliases.model_constants import MANAGED_EXECUTOR_SERVICE_TEMPLATE
6566
from wlsdeploy.aliases.model_constants import MANAGED_SCHEDULED_EXECUTOR_SERVICE_TEMPLATE
6667
from wlsdeploy.aliases.model_constants import MANAGED_THREAD_FACTORY_TEMPLATE
6768
from wlsdeploy.aliases.model_constants import ODL_CONFIGURATION
6869
from wlsdeploy.aliases.model_constants import OHS
6970
from wlsdeploy.aliases.model_constants import OPSS_INITIALIZATION
71+
from wlsdeploy.aliases.model_constants import PLUGIN_DEPLOYMENT
7072
from wlsdeploy.aliases.model_constants import RCU_DB_INFO
7173
from wlsdeploy.aliases.model_constants import REMOTE_CONSOLE_HELPER
7274
from wlsdeploy.aliases.model_constants import RESOURCE_MANAGER
@@ -176,8 +178,9 @@ class AliasEntries(object):
176178
]
177179

178180
__app_deployments_top_level_folders = [
179-
'Application',
180-
'Library'
181+
APPLICATION,
182+
LIBRARY,
183+
PLUGIN_DEPLOYMENT
181184
]
182185

183186
__domain_info_top_level_folders = [

core/src/main/python/wlsdeploy/aliases/model_constants.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
CAPACITY = 'Capacity'
3838
CDI_CONTAINER = 'CdiContainer'
3939
CERT_PATH_PROVIDER = 'CertPathProvider'
40+
CERT_REVOC = 'CertRevoc'
41+
CERTIFICATE_MANAGEMENT = 'CertificateManagement'
4042
CERTIFICATE_REGISTRY = 'CertificateRegistry'
4143
CLASSPATH = 'ClassPath'
4244
CLIENT_PARAMS = 'ClientParams'
@@ -75,6 +77,7 @@
7577
CREDENTIAL = 'Credential'
7678
CREDENTIAL_ENCRYPTED = 'CredentialEncrypted'
7779
CREDENTIAL_MAPPER = 'CredentialMapper'
80+
CREDENTIAL_SET = 'CredentialSet'
7881
CROSS_DOMAIN = 'CrossDomain'
7982
CUSTOM_DBMS_AUTHENTICATOR = 'CustomDBMSAuthenticator'
8083
CUSTOM_RESOURCE = "CustomResource"
@@ -234,6 +237,7 @@
234237
PLAN_DIR = 'PlanDir'
235238
PLAN_PATH = 'PlanPath'
236239
POLICY = 'Policy'
240+
PLUGIN_DEPLOYMENT = 'PluginDeployment'
237241
PREPEND = 'prepend'
238242
PROPERTIES = 'Properties'
239243
PRODUCTION_MODE_ENABLED = 'ProductionModeEnabled'
@@ -433,6 +437,7 @@
433437
PASSWORD = 'Password'
434438
PATH_TO_SCRIPT = 'PathToScript'
435439
PLAN_STAGING_MODE = 'PlanStagingMode'
440+
PLUGIN_TYPE = 'PluginType'
436441
RESOURCE_CLASS = 'ResourceClass'
437442
SECURITY_DD_MODEL = 'SecurityDDModel'
438443
SET_OPTION_APP_DIR = 'AppDir'

core/src/main/python/wlsdeploy/tool/create/domain_creator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ def __deploy(self):
275275
"""
276276
self.model_context.set_domain_home(self._domain_home)
277277
self.__set_domain_attributes()
278+
self.model_deployer.deploy_plugins()
278279
self.__configure_security_configuration()
279280
self.__deploy_resources_and_apps()
280281
self.wlst_helper.update_domain()

core/src/main/python/wlsdeploy/tool/create/security_provider_creator.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
"""
55

66
from oracle.weblogic.deploy.exception import BundleAwareException
7+
from oracle.weblogic.deploy.util import PyOrderedDict as OrderedDict
78

89
from wlsdeploy.aliases.location_context import LocationContext
910
from wlsdeploy.aliases.model_constants import AUTHENTICATION_PROVIDER
11+
from wlsdeploy.aliases.model_constants import CERTIFICATE_MANAGEMENT
1012
from wlsdeploy.aliases.model_constants import DEFAULT_AUTHENTICATOR
1113
from wlsdeploy.aliases.model_constants import DEFAULT_REALM
1214
from wlsdeploy.aliases.model_constants import PASSWORD_DIGEST_ENABLED
@@ -221,6 +223,28 @@ def _process_child_nodes(self, location, model_nodes):
221223

222224
Creator._process_child_nodes(self, location, model_nodes)
223225

226+
# Override
227+
def _create_subfolders(self, location, model_nodes):
228+
"""
229+
Create the child MBean folders at the specified location.
230+
In the SecurityConfiguration folder, be sure CertificateManagement subfolder is after CredentialSet.
231+
:param location: the location
232+
:param model_nodes: the model dictionary
233+
:raises: CreateException: if an error occurs
234+
"""
235+
_method_name = '_create_subfolders'
236+
237+
new_model_nodes = model_nodes
238+
model_type, model_name = self.aliases.get_model_type_and_name(location)
239+
if model_type == SECURITY_CONFIGURATION:
240+
certificate_nodes = dictionary_utils.get_dictionary_element(model_nodes, CERTIFICATE_MANAGEMENT)
241+
if certificate_nodes:
242+
new_model_nodes = OrderedDict(model_nodes)
243+
del new_model_nodes[CERTIFICATE_MANAGEMENT]
244+
new_model_nodes[CERTIFICATE_MANAGEMENT] = certificate_nodes
245+
246+
Creator._create_subfolders(self, location, new_model_nodes)
247+
224248
def _delete_existing_providers(self, location):
225249
"""
226250
The security realms providers in the model are processed as merge to the model. Each realm provider

0 commit comments

Comments
 (0)